Как избежать окна консоли с файлом.pyw, содержащим системный вызов os.s?

Если я сохраню свои файлы кода как .pyw, не появляется окно консоли - это то, что я хочу - но если код включает в себя вызов os.systemЯ все еще получаю надоедливое окно консоли. Я полагаю, это вызвано звонком os.system, Есть ли способ выполнить другие файлы из моего .pyw скрипт без поднятия окна консоли вообще?

6 ответов

Решение

Вы можете попробовать использовать модуль подпроцесса (subprocess.Popen, subprocess.call или что угодно) с аргументом shell=True если вы хотите избежать запуска консольного окна.

Решение, которое описывает Петр, на самом деле не так сложно, как может показаться. Вот пример, где startupinfo передается check_call вызов для подавления окна консоли:

startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW

subprocess.check_call(cmd, startupinfo=startupinfo)

Поскольку функции удобства call, check_call, а также check_output переслать их **kwargs к Popen конструктор, не требуется использовать Popen непосредственно.

Вы должны использовать subprocess.Popen прохождение класса как startupinfo экземпляр значения параметра subprocess.STARTUPINFO класс с dwFlags атрибут холдинга subprocess.STARTF_USESHOWWINDOW флаг и wShowWindow атрибут холдинга subprocess.SW_HIDE флаг. Это может быть выведено из чтения строк 866-868 subprocess.py исходный код. Может быть необходимо также передать subprocess.CREATE_NEW_CONSOLE пометить как значение creationflags параметр при запуске pythonw.exe который не открывает консоль.

Когда вы используете shell=True бывает так, что все вышеперечисленное установлено правильно, но это не значит, что это правильное решение. Я бы сказал, что это не потому, что это увеличивает накладные расходы на запуск интерпретатора команд и анализ аргументов. Кроме того, следует помнить, что (...) использование shell=True настоятельно не рекомендуется в тех случаях, когда командная строка создается из внешнего ввода в соответствии с документацией модуля подпроцесса.

Люди немного ленивые... Я бы поблагодарил @Piotr Dobrogost и @Frank S. Thomas за их ответы.

Я пришел с этим кодом, который работает на Linux и Windows:

import platform
import subprocess
startupinfo = None
if platform.system() == 'Windows':
    import _subprocess  # @bug with python 2.7 ?
    startupinfo = subprocess.STARTUPINFO()
    startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
    startupinfo.wShowWindow = _subprocess.SW_HIDE

Потом...

args = [exe, ...]
out = subprocess.check_output(args, startupinfo=startupinfo)

Спасибо ребята;)

Дополнительно: просто чтобы заметить, что следующий код, использующий call, также работает на Python 2.7 (в Windows) с приведенным выше кодом startupinfo:

def run_command(cmd, sin, sout):
    print "Running cmd : %s"%(" ".join(cmd) )
    return subprocess.call( cmd, stdin=sin, stdout=sout, startupinfo=startupinfo)

Похоже, что os.popen не выводит окно консоли. Скрипт работает под 'pythonw'. Не уверен во всех случаях, но в моем случае это работает хорошо.

os.popen(command)

Подобно тому, что сказал @firsthand, я читал на форумах пользователей wxPython, что вы "заменяете" текущее работающее приложение, которое будет "command.com" или "CMD.exe", на pyw.exe или pythonw.exe когда вы используете что-то вроде следующего:

os.execl(sys.executable, *([sys.executable]+sys.argv))

см другой пост

Хотя я не знаю, как бы вы поступили в этом случае.

Я считаю, что одним из преимуществ этого подхода является то, что если вы запускаете свой скрипт несколько раз на панели задач ОС, не заполняясь значками CMD. С другой стороны, если у вас есть несколько CMD, свернутых на панели задач, и начинаете закрывать их, невозможно определить, какой CMD подходит к какому сценарию Pythonw.

Другие вопросы по тегам