0

我需要从 PHP 脚本调用 python 脚本并将结果返回给 PHP。我玩proc_open功能。但它不起作用。你知道为什么吗?这是 PHP 脚本:

$msg = "this is a new message \n bla ble !@#$%^&*%(*))(_+=-";
$descriptorspec = array(
0 => array("pipe","r"),
1 => array("pipe","w"),
2 => array("file","./error.log","a")
) ;
$cwd = './' ;
$command = 'python ./upper.py ';
$proc = proc_open($command, $descriptorspec, $pipes, $cwd) ;
if ( is_resource( $proc ) ) {
    fwrite( $pipes[0], $msg );
    fclose( $pipes[0] );
    fclose( $pipes[1] );
    proc_close($proc);
    echo "proc is closed\n";
}
else {
    echo 'proc is not a resource';
}

python `upper.py' 脚本

import sys
print 'in python script'

data = sys.stdin.readlines()
print data

输出是:

in php script
proc is closed

我在error.log中有错误:

close failed in file object destructor:
sys.excepthook is missing
lost sys.stderr
4

1 回答 1

0

以防万一答案对任何人都很重要:

发生错误是因为您在$pipes[1]python 脚本有机会编写它之前立即关闭,甚至很可能在它开始运行之前。我的系统(Mac)上的错误是:

close failed: [Errno 32] Broken pipe

(只是出于好奇,你运行的是什么类型的系统,它会给你这个奇怪的信息?)

无论如何,您可以通过在关闭管道之前读取管道来避免错误,例如,

stream_get_contents($pipes[1]);

这保证了 python 脚本将有机会在管道仍处于打开状态时写入管道(至少一次)。

如果您是 python 脚本的作者,那么让它写入输出没有多大意义,除非您的 PHP 脚本要读取它所写的内容。

另一方面,如果 python 脚本不是您制作的,并且它写入您不关心的输出,您可能可以通过玩一些游戏来避免读取输出pcntl_wait()or pcntl_waitpid()—— 尽管我不会赌它。一个更安全的选择可能是只读取输出流并将它们扔在地板上。

(提出了一个有趣的问题,无论您是否关心输出:如果您事先不知道输出的结尾会是什么样子,并且子进程在您关闭管道并调用之前不会退出proc_close(),你怎么知道子进程什么时候真正完成了你叫它做的事情?)

另一种选择(到目前为止我未经测试)可能是将您不关心的任何输出流连接到描述符,例如:

array("file", "/dev/null", "w")

/dev/null或您的系统上的任何等价物。

于 2012-12-23T03:22:17.617 回答