无法从PHP执行Python脚本

11
我想从PHP文件中执行Python脚本。我能够执行简单的Python脚本,例如:

I want to execute Python script from PHP file. I am able to execute simple python script like:

print("Hello World") 

但是当我想执行以下脚本时,什么也没有发生

from pydub import AudioSegment
AudioSegment.converter = "/usr/bin/ffmpeg"
sound = AudioSegment.from_file("/var/www/dev.com/public_html/track.mp3")
sound.export("/var/www/dev.com/public_html/test.mp3", format="mp3", bitrate="96k")

当我从终端执行相同的脚本时,它能够正常工作。以下是我的 PHP 脚本:

and same script works fine when I execute it from terminal. here is my php script:

$output = shell_exec("/usr/bin/python /var/www/dev.com/public_html/index.py");
echo $output;

我也尝试了以下方法,但没有成功:

$output = array();
$output = passthru("/usr/bin/python /var/www/dev.com/public_html/index.py");
print_r($output);

请帮助我


我也尝试了stackoverflow上提供的其他解决方案。它们都可以打印“Hello World”,但对于我的上述脚本无效。 - Rajinder
当在bash shell中运行时,您的环境将与使用shell_exec时不同。如果您知道缺少哪些环境变量,可以通过PHP脚本使用putenv("VARIABLE=value");来设置它们。 - Chris Wheeler
尝试通过将代码放入一个函数中并调用它来添加日志记录和正确的编码实践,并捕获发生的异常然后进行记录。通过引发错误来测试,以验证日志记录是否正常工作。然后尝试通过PHP运行它。 - deets
是的,这是由于缺少环境变量造成的。但我不知道如何从PHP中设置它们。 - Rajinder
我尝试了putenv('PATH=/usr/bin/ffmpeg:$PATH which ffmpeg');但它没有起作用。 - Rajinder
"没有运气"就像没有调试信息一样。立即阅读发生了什么错误并进行调试。周围没有水晶球可用... - helvete
6个回答

4

PHP的passthru函数没有一种优雅的方法来传递环境变量。如果你必须使用passthru,那么直接在命令中导出你的变量:

passthru("SOMEVAR=$yourVar PATH=$newPATH ... /path/to/executable $arg1 $arg2 ...")

如果你倾向于使用 shell_exec,那么你可能会喜欢 putenv 更加简洁的接口:

putenv("SOMEVAR=$yourVar");
putenv("PATH=$newPATH");
echo shell_exec("/path/to/executable $arg1 $arg2 ...");

如果您愿意采用更加复杂(但更强大)的方法,请考虑使用proc_open函数:

$cmd = "/path/to/executable arg1 arg2 ..."

# Files 0, 1, 2 are the standard "stdin", "stdout", and "stderr"; For details
# read the PHP docs on proc_open.  The key here is to give the child process a
# pipe to write to, and from which we will read and handle the "passthru"
# ourselves
$fileDescriptors = array(
    0 => ["pipe", "r"],
    1 => ["pipe", "w"],
    2 => ["pipe", "w"]
);

$cwd = '/tmp';
$env = [
    'PATH' => $newPATH,
    'SOMEVAR' => $someVar,
    ...
];

# "pHandle" = "Process handle".  Note that $pipes is new here, and will be
# given back to us
$pHandle = proc_open($cmd, $fileDescriptors, $pipes, $cwd, $env);

# crucial: did proc_open work?
if ( is_resource( $pHandle ) ) {
    # $pipes is now valid
    $pstdout = $pipes[ 1 ];

    # Hey, whaddya know?  PHP has just what we need...
    fpassthru( $pstdout );

    # Whenever you proc_open, you must also proc_close.  Just don't
    # forget to close any open file handles
    fclose( $pipes[0] );
    fclose( $pipes[1] );
    fclose( $pipes[2] );
    proc_close( $pHandle );
}

谢谢您的回答。我尝试了您的建议,但它没有起作用。 - Rajinder
@Rajinder 这意味着您的设置中可能存在拼写错误或其他问题。这是一个众所周知的范例,我刚刚进行了测试以确认它可以正常工作。如果社区要提供帮助,您需要提供更多信息。"它不起作用"并不是一个有用的回答。它到底是怎么不起作用的?您实际尝试了什么?您收到了什么错误消息? - hunteke

2

根据您的回复,您想从PHP执行Python脚本。

我使用以下代码成功执行了它:

$command = escapeshellcmd('/var/www/yourscript.py');
$output = shell_exec($command);
echo $output;

请使用上述PHP代码与相同的Python脚本。首先尝试将Python脚本作为GCI脚本运行,以确保其正常工作,并按照我之前提到的设置权限为公共目录和脚本。
===================旧回答============================
根据您的要求,我猜想您想要做的是像http://localhost/yourscript.py一样将其作为CGI脚本运行。
而且,为什么您要使用PHP来执行Python脚本,而不是直接作为CGI脚本运行呢?
以下是使其像网页一样工作所需执行的步骤:
1. 在Apache(或您正在使用的Web服务器)中启用Python CGI。
2. 将脚本放在已配置为CGI的目录中。
3. 添加适当的代码以使其作为CGI脚本工作。
#!/usr/local/bin/python from pydub import AudioSegment AudioSegment.converter = "/usr/local/bin/ffmpeg" sound = AudioSegment.from_file("/var/www/dev.com/public_html/track.mp3") sound.export("/var/www/dev.com/public_html/test.mp3", format="mp3", bitrate="96k") print "Content-type: text/html" print print "" print "" print "" print "Done/ you can perform some conditions and print useful info here" print ""
4. 赋予脚本权限并使公共目录可写。
5. 访问脚本http://localhost/your-path-to-script.py
我已成功运行此程序。如果您需要其他帮助,请告诉我。

感谢您的回答。我的需求是从PHP运行Python脚本,因为我的主要应用程序是PHP,但我想从Python运行一些脚本。 - Rajinder
@Rajinder,我已经编辑了我的帖子,并附上了可工作的PHP代码,请检查并告诉我是否遇到任何问题。 - joginder singh
@Rajinder,你有没有机会检查我的更新答案? - joginder singh

2
在我的情况下,我写了这段代码。
<?php
chdir('/home/pythontest') ; // python code dir
$commandline="/usr/bin/python3 test.py parameter" ;
exec($commandline, $output, $error) ;
echo $output ;
?>

如果您需要为Python设置一些环境,请像这样添加环境变量。
$commmandline="LANG=en_US.utf8 LC_ALL=en_US.utf8 /usr/bin/python3 ..." ;

并检查httpd日志。


谢谢你的回答。我尝试了你的建议,但它没有起作用。 - Rajinder

1

请看这里:

Apache用户必须在sudoers文件中,最好不要给予apache sudo权限,而是给予apache(www-data)用户运行您的Python程序的权限。

将以下第一行放入您的Python脚本中:#!/usr/bin/env python,以便脚本知道使用哪个程序打开它。

然后,

更改组:

chgrp www-data /path/to/python-script.py

make it executabe:

chmod +x /path/to/python-script.py

然后尝试它:
shell_exec("/path/to/python-script.py");

我希望这个能够工作! :)

谢谢你的回答。我尝试了你的建议,但它不起作用。 - Rajinder

0

你也可以直接执行FFmpeg而不需要Python:

$output = shell_exec("/usr/bin/ffmpeg -i in.mp3 -b:a 96k out.mp3");
echo $output;

FFmpeg文档


0

回答于2022年。

在php 8.0及以上版本中,以下方法有效。上面的答案非常有用,但我在这里编译了一些额外的步骤。

PHP代码。

$output = shell_exec("python3 /var/www/python/test.py");
print_r($output);

exec('python3 --version 2>&1', $output);
var_dump($output);

尝试使用shell_exeexec

  1. 确保Python文件具有可执行权限并添加到www-data组(如果是Ubuntu/Debian系统)。sudo chmod +x test.pysudo chgrp www-data test.py

  2. 确保php.ini已禁用函数行注释或为空。

sudo vim sudo vim /etc/php/8.0/cli/php.ini sudo vim sudo vim /etc/php/8.0/apache2/php.ini

对于两者都要这样做。

我制作了一个简单的视频,以确保其他人不会花费更多时间来解决问题。 https://youtu.be/t-f6b71jyoM


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接