我需要使用subprocess.Popen
启动一些长时间运行的进程,并希望每个进程自动管道stdout
和stderr
以分隔日志文件。每个进程将同时运行几分钟,我希望在进程运行时写入两个日志文件(stdout
和stderr
)每个进程。
我是否需要在循环中的每个进程上不断调用p.communicate()
以更新每个日志文件,或者是否有某种方法可以调用原始Popen
命令以便stdout
和stderr
会自动流式传输以打开文件句柄吗?
答案 0 :(得分:69)
您可以将stdout
和stderr
作为参数传递给Popen()
subprocess.Popen(self, args, bufsize=0, executable=None, stdin=None, stdout=None,
stderr=None, preexec_fn=None, close_fds=False, shell=False,
cwd=None, env=None, universal_newlines=False, startupinfo=None,
creationflags=0)
例如
>>> import subprocess
>>> with open("stdout.txt","wb") as out, open("stderr.txt","wb") as err:
... subprocess.Popen("ls",stdout=out,stderr=err)
...
<subprocess.Popen object at 0xa3519ec>
>>>
答案 1 :(得分:36)
每the docs,
stdin,stdout和stderr指定了 执行程序的标准输入, 标准输出和标准错误 文件句柄。有效 值是PIPE,一个现有文件 描述符(正整数),an 现有文件对象,无。
所以只需将open-for-writing文件对象作为命名参数stdout=
和stderr=
传递给你,你应该没问题!
答案 2 :(得分:2)
我同时运行两个子进程,并将两者的输出保存到单个日志文件中。我还建立了一个超时来处理挂起的子进程。当输出太大时,超时总是触发,并且任何一个子进程的stdout都不会保存到日志文件中。亚历克斯上面提出的答案并没有解决它。
# Currently open log file.
log = None
# If we send stdout to subprocess.PIPE, the tests with lots of output fill up the pipe and
# make the script hang. So, write the subprocess's stdout directly to the log file.
def run(cmd, logfile):
#print os.getcwd()
#print ("Running test: %s" % cmd)
global log
p = subprocess.Popen(cmd, shell=True, universal_newlines = True, stderr=subprocess.STDOUT, stdout=logfile)
log = logfile
return p
# To make a subprocess capable of timing out
class Alarm(Exception):
pass
def alarm_handler(signum, frame):
log.flush()
raise Alarm
####
## This function runs a given command with the given flags, and records the
## results in a log file.
####
def runTest(cmd_path, flags, name):
log = open(name, 'w')
print >> log, "header"
log.flush()
cmd1_ret = run(cmd_path + "command1 " + flags, log)
log.flush()
cmd2_ret = run(cmd_path + "command2", log)
#log.flush()
sys.stdout.flush()
start_timer = time.time() # time how long this took to finish
signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(5) #seconds
try:
cmd1_ret.communicate()
except Alarm:
print "myScript.py: Oops, taking too long!"
kill_string = ("kill -9 %d" % cmd1_ret.pid)
os.system(kill_string)
kill_string = ("kill -9 %d" % cmd2_ret.pid)
os.system(kill_string)
#sys.exit()
end_timer = time.time()
print >> log, "closing message"
log.close()