Подпроцесс Popen не работает с pythonw.exe

Я хочу получить содержимое stdout и stderr, когда я запускаю следующий script в Windows с помощью pythonw.exe:

import subprocess
import sys
import os
import string
import time

tmpdir = 'c:/temp'
cmd = 'dir c:'

tmpfile = "tmp_%f" % (time.time())
tmpfile = os.path.normpath(os.path.join(tmpdir,tmpfile))
tmpfile2 = tmpfile+".bat"
tmpfile3 = tmpfile+".txt"

fa = open(tmpfile2,'w')
fa.write("@ECHO OFF > NUL\n")
fa.write('call '+cmd+"\n")
fa.close()

wcmd = []
wcmd.append(tmpfile2)

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

fb = open(tmpfile3,'w')
fb.write("\n")
fb.write(tmpfile2+"\n")

try:
    procval = subprocess.Popen(wcmd, startupinfo=startupinfo, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()
    fb.write(str(procval)+"\n")
    fb.write("Sucess")
    fb.close()
except:
    fb.write(str(procval)+"\n")
    fb.write("Failure")
    fb.close()

Когда я выполняю его с помощью python.exe, я получаю ожидаемый результат. Когда я запускаю его с помощью pythonw.exe Я заканчиваю на стороне исключения. Если я запускаю popen только с помощью команды и флаги startupinfo, команда будет успешно завершена, но не будет доступа к данным в дочерних процессах. Все, что я прочитал, говорит, что это должно работать, но должно быть что-то упустить. Любая помощь будет принята с благодарностью.

Спасибо, Ренди

Ответ 1

Возможно, это ошибка при использовании pythonw.exe

pythonw.exe запускает процесс демона, который не имеет нормального доступа к дескрипторам стандартных файлов. Единственное, что вам нужно сделать в script, - это установить 3-й fd для stdin:

p = subprocess.Popen(wcmd,
                     startupinfo=startupinfo,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.STDOUT,
                     stdin=subprocess.PIPE)
procval = p.communicate()

Ответ 2

(Несколько лет спустя с этим ответом...) Я столкнулся с одной и той же проблемой и обнаружил, что вы должны заменить это:

STDOUT = subprocess.PIPE

с этим:

STDIN = subprocess.PIPE

Здесь я предполагаю основную проблему: pythonw запускает процесс без stdin (имеет смысл, поскольку нет консоли). Подпроцесс пытается получить доступ к stdin, и это вызывает ошибку.

Альтернативой является использование /dev/null для stdin, см. этот поток для обсуждения того, как это сделать: Игнорирование вывода из подпроцесса .Popen (кроме вас "Я хочу использовать devnull на stdin).