stdout
and stderr
arguments of subprocess.Popen
allow you to
redirect standard outputs to different kind of stream.
stdin, stdout
and stderr specify the executed program’s standard input, standard
output and standard error file handles, respectively. Valid values are
PIPE, an existing file descriptor (a positive integer), an existing
file object, and None. [...] the child’s file handles will be inherited from the
parent. Additionally, stderr can be STDOUT, which indicates that the
stderr data from the child process should be captured into the same
file handle as for stdout.
You might want to try to redirect the output to file here but you won't have the pid of the child process to properly name the output file.
If your script runs on Unix, you can also try to pass a callable object to Popen
's argument preexec_fn
which would replace the default output stream with a file handler. With this solution, you can actually get the current process pid with os.getpid
.
If preexec_fn is set to a callable object, this object will be called
in the child process just before the child is executed. (Unix only)
I did some tests with the preexec_fn
solution and just replacing sys.stdout
doesn't work. But doing it at the file descriptor level seems to work.
def redirect_output():
import sys, os
# The opened file needs to stay alive
redirect_output._file = open('{}.log'.format(os.getpid()), 'w')
os.dup2(redirect_output._file.fileno(), sys.stdout.fileno())
sub = subprocess.Popen(['ls'], preexec_fn=redirect_output)
Of course, this is a quick example, some polishing might be needed.
The above example seems to work ok when shell = False
but in the case of shell = True
, you get the pid of the shell. One way to work around that is to use bash
and exec
to run the command.
command = 'python -c "import os; print \'\\\'\'process: \'\\\'\', os.getpid()"'
sub = subprocess.Popen(["bash -c 'exec {} > $$.log'".format(command)],
shell = True,
preexec_fn = os.setsid
)
print 'Shell: ', sub.pid
Here os.setsid
is used to handle properly termination of the spawned process.