php - 使用 popen 执行多处理脚本时输出困惑

标签 php c multiprocessing pipe 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之类的命令

最佳答案

回答我的问题:

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

来自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)

关于php - 使用 popen 执行多处理脚本时输出困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24552295/

相关文章:

php - move_uploaded 文件 :failed to open stream: Permission denied in/srv/http/upload. php

c - 结构成员中的 void 指针和函数指针

c - 为什么在执行 C 程序时出现错误,显示终端中没有此类目录?

Python无法启动新线程多处理

python - 使用 python 多处理将数据推送到 Kafka 队列

c - 让 children 等待直到收到 parent 的信号

php - 如何防止 PHP 中的 SQL 注入(inject)?

php - 如何更改 Laravel 模型表名称

php - 使用已使用 filter_input() 过滤的 htmlspecialchars() 从数据库输出数据

C 要求结构或 union 至少有一个成员