2015-02-12 68 views
0

关于如何处理子进程,异步IO输出和避免PIPE死锁的堆栈溢出,有很多很好的答案。虽然有些东西对我来说并没有消失,我需要一些关于如何完成以下内容的指导。从子进程持续处理大量的stdout和stderr

我想从我的python程序运行一个子进程。子进程会产生大量的标准输出,如果情况变差,会产生一点标准错误。子进程本身需要大约20分钟才能完成。对于生成的输出和错误,我希望能够将它们记录到终端,并将其写入日志文件。

做后者很容易。我刚打开两个文件,然后设置为Popen对象上的stdout和stderr。但是,也将输出捕获为行,以便我可以将它们连续打印到终端,这让我很烦恼。我想我可以使用poll()方法来持续轮询。尽管如此,我仍然需要使用PIPE作为stdout和stderr,并且在它们上调用read()会阻塞到EOF。

我想我试图做到的是:

start the subprocess 
    while process is still running 
     if there are any lines from stdout 
      print them and write them to the out log file 
     if there are any lines from stderr 
      print them and write them to the err log file 
     sleep for a little bit 

这是否看起来是合理的?如果是这样,有人可以解释一下如何在不阻塞的情况下实施'if'部分。

感谢

+0

关于这个问题的其他问题表明,没有非阻止读取可用?这意味着你将不得不使用异步或选择 - 否则读取将阻塞,直到EOF。确保你正在刷新子进程中的sys.stdout。 print(flush = True)似乎不适用于我。 – user3467349 2015-02-12 01:01:00

+1

async.io:[Subprocess.Popen:将stdout和stderr都复制到终端和变量](http://stackoverflow.com/a/25960956/4279) – jfs 2015-02-12 02:02:34

+0

多线程:[Python子进程将儿童输出到文件和终端?] (http://stackoverflow.com/a/4985080/4279) – jfs 2015-02-12 02:03:23

回答

2

这里是我的select.select版本:

子过程(foo.py):

import time 
import sys 

def foo(): 
    for i in range(5): 
     print("foo %s" %i, file=sys.stdout,)#flush=True 
     sys.stdout.flush() 
     time.sleep(7) 
foo() 

主营:

import subprocess as sp 
import select 
proc= sp.Popen(["python", "foo.py"], stderr=sp.PIPE, stdout=sp.PIPE) 
last_line = "content" 
while last_line: 
    buff = select.select([proc.stdout], [], [], 60)[0][0] 
    if not buff: 
     print('timed out') 
     break 
    last_line = buff.readline() 
    print(last_line) 
+1

谁投下了这个票,你能解释一下为什么吗? – 2015-02-12 02:48:43

+0

我很困惑。 – user3467349 2015-02-12 03:12:48

+1

当OP询问时,代码也应该从'proc.stderr'中读取。 'readline()'可能会在'select()'后面阻塞,而是使用'os.read()'。 “超时”并不意味着所有的输出都被读取;不要过早地打破循环。写入输出到一个文件也OP作出要求。使用管道的select()不适用于Windows。按照上面评论中的链接查看便携式解决方案。 – jfs 2015-02-12 13:46:01