pipe道输出的subprocess。打开到文件
我需要使用subprocess.Popen
启动一些长时间运行的进程,并希望从每个自动pipe道的stdout
和stderr
单独的日志文件。 每个进程将同时运行几分钟,并且我希望每个进程有两个日志文件( stdout
和stderr
)在进程运行时写入。
为了更新每个日志文件,是否需要在循环中的每个进程上不断调用p.communicate()
,还是有一些方法来调用原始Popen
命令,以便stdout
和stderr
自动stream式传输以打开文件句柄?
根据文档 ,
stdin,stdout和stderr分别指定执行程序的标准input,标准输出和标准错误文件句柄。 有效值是PIPE,现有文件描述符(正整数),现有文件对象和None。
所以只需将打开的文件对象作为命名参数stdout=
和stderr=
传递就可以了。
您可以将stdout
和stderr
作为parameter passing给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> >>>
我同时运行两个subprocess,并将两者的输出保存到一个日志文件中。 我也build立了超时处理挂起的subprocess。 当输出变得太大时,超时总是触发,并且任何一个subprocess的stdout都不会被保存到日志文件中。 上面Alex提出的答案并不能解决这个问题。
# 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()