使用popen执行多处理脚本时输出混乱


Disordered output while executing multi-processed script using popen

我一直在尝试在php中使用popen命令执行多处理python程序。

问题是,输出顺序不是预期的。PHP代码为

if ( ($fp = popen("python multi-processed.py 2>&1", "r")) )
{
    while( !feof($fp) )
    {
        print fread($fp, 1024);
        ob_flush();
        flush();
    }
    fclose($fp);
}
else
    print "can't execute command";

但是当我在shell中运行这个命令时,我得到的是预期顺序的输出

python multi-processed.py 2>&1
然后我想到了管道缓冲,用C写了下面的代码
FILE *fp = popen("python multi-processed.py -u", "r");
if(fp != NULL)
{
    setvbuf(fp, 0, _IONBF, 0);
    while (!feof(fp))
    {
        fgets(buffer, 1024, fp);
        puts(buffer);
        fflush(fp);
    }
    fclose(fp);
}

这里我通过调用setvbuf(fp, 0, _IONBF, 0);来关闭管道缓冲,但是输出顺序不是预期的。

编辑:添加python文件:multi-processed.py

def foo():
    print 'in foo'
    sleep(2)
    print 'in foo after sleep'
def fun():
    print 'in fun'
    sleep(2)
    print 'in fun after sleep'
if __name__ == '__main__':
    p1 = Process(target=foo, args=())
    p2 = Process(target=fun, args=())
    p1.start()
    p2.start()
    p1.join()
    p2.join()
预期输出:

in foo
in fun
in foo after sleep
in fun after sleep
实际输出:

in foo
in foo after sleep
in fun
in fun after sleep
你能帮我解决这个问题吗?

PS:我用的是windows机器,不能运行unbuffer等命令

回答我的问题:

问题是stdout缓冲。可以通过将每次写入都刷新到标准输出来纠正。

从https://stackoverflow.com/a/107717/1519642,添加下面的代码解决了问题

import sys
class Unbuffered(object):
   def __init__(self, stream):
       self.stream = stream
   def write(self, data):
       self.stream.write(data)
       self.stream.flush()
   def __getattr__(self, attr):
       return getattr(self.stream, attr)
sys.stdout = Unbuffered(sys.stdout)