Reputation: 121
I want to be able to get the contents of stdout and stderr when I run the following script on windows using 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()
When I execute it using python.exe I get the expected output. When I run it using pythonw.exe I end up on the exception side. If I run the popen with just the command and the startupinfo flags the command will successfully complete but no access to the data in the child processs. Everything that I read stated that this should work but must be missing something. Any help would be greatly appreciated.
Thanks, Randy
Upvotes: 12
Views: 4399
Reputation: 12296
(A few years late with this answer...) I've run across the same problem and found that you should replace this:
stdout=subprocess.PIPE
with this:
stdin=subprocess.PIPE
Here's my guess at the underlying problem: pythonw launches the process with no stdin (makes sense, since there is no console). The sub-process tries to access stdin and this causes an error.
An alternative is to use /dev/null for stdin, see this thread for a discussion on how to do that: Ignoring output from subprocess.Popen (except you'll want to use devnull on stdin).
Upvotes: 4
Reputation: 92647
This is possibly a bug when using pythonw.exe
pythonw.exe starts a daemon process which doesn't have the normal access to the standard file descriptors. The only thing you would need to do in your script is to specifically set the 3rd fd for stdin:
p = subprocess.Popen(wcmd,
startupinfo=startupinfo,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
stdin=subprocess.PIPE)
procval = p.communicate()
Upvotes: 11