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

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

Ответ 1

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

Ответ 2

Вы должны использовать 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, просто случается, что все вышеперечисленное задано правильно, но это не значит, что это правильное решение. Я бы сказал, что это не потому, что он добавляет накладные расходы на выполнение интерпретатора команд и аргументов анализа. Кроме того, вы должны иметь в виду, что (...) использование оболочки = True сильно обескуражено в случаях, когда командная строка построена из внешнего ввода в соответствии с документацией модуля подпроцесса.

Ответ 3

Решение, которое описывает Петр, на самом деле не так сложно, как может показаться. Вот пример, когда 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.

Ответ 4

Люди немного ленивы... Я бы хотел, чтобы они отвечали.

@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)

спасибо guys;)

Дополнительно: просто отметим, что следующий код с использованием "вызова" также работает на 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)

Ответ 5

Кажется, что "os.popen" не создает консольное окно. Script работает под "pythonw". Не уверен во всех случаях, но в моем случае это работает хорошо.

os.popen(command)

Ответ 6

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

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

см. другое сообщение

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

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