使用proc_open进行多流选择,接收慢进程的响应

1 投票
1 回答
902 浏览
提问于 2025-04-18 08:00

我在一个WordPress插件中使用proc_open来调用一个比较慢的Python脚本(echonest remix代码),这个方法是参考了这个问题中的一些代码。

这个Python脚本处理一堆音频数据,大约需要一分钟的时间。我希望能找到一种方法,让浏览器能够实时显示Python脚本输出的内容。现在的情况是,我整个函数的输出在proc_open和stream_select的过程结束之前都不会显示出来,包括函数开始时的一个echo语句。

<?php
echo "Why wait before printing me out?";

$description = array (     
    0 => array("pipe", "r"),  // stdin
    1 => array("pipe", "w"),  // stdout
    2 => array("pipe", "w")   // stderr
);

$application_system = "python ";
$application_name .= "glitcher/glitchmix.py";
$application = $application_system.$application_name.$separator;

$argv1 = 'a variable';
$argv2 = 'another variable';
$separator = " ";

$pipes = array();

$proc = proc_open ( $application.$separator.$argv1.$separator.$argv2, $description , $pipes, glitch_player_DIR);

// set all streams to non blockin mode
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);

// get PID via get_status call
$status = proc_get_status($proc);
// status check here if($status === FALSE)

$pid = $status['pid'];
// now, poll for childs termination
while(true) {
    // detect if the child has terminated - the php way
    $status = proc_get_status($proc);
    //  retval checks : ($status === FALSE) and ($status['running'] === FALSE)

    // read from childs stdout and stderr
    // avoid *forever* blocking through using a time out (1sec)
    foreach(array(1, 2) as $desc) {
        // check stdout for data
        $read = array($pipes[$desc]);
        $write = NULL;
        $except = NULL;
        $tv = 1;
        $n = stream_select($read, $write, $except, $tv);
        if($n > 0) {
            do {
                $data = fgets($pipes[$desc], 8092);
                echo $data . "\n<br/>";
            } while (strlen($data) > 0);
        }
    }
}
?>

有没有可能使用多次调用stream_select,来实时显示子进程的输出呢?

显然我对socket编程还很陌生,希望能从Stack Overflow社区得到更多的帮助。

1 个回答

0

这真是个有趣又简单的原因。看看Python的-u选项。我在同一个问题上浪费了两天时间。当我用bash替代Python,并测试一些来自bash脚本的输出时,它立刻就收到了。

撰写回答