从 PHP 运行 Python 脚本


Running a Python script from PHP

我正在尝试使用以下命令从PHP运行Python脚本:

exec('/usr/bin/python2.7 /srv/http/assets/py/switch.py arg1 arg2');

但是,PHP 根本不会产生任何输出。错误报告设置为 E_ALL 和 display_errors 处于打开状态。

这是我尝试过的:

  • 我用python2/usr/bin/python2python2.7而不是/usr/bin/python2.7
  • 我还使用了相对路径而不是绝对路径,这也不会改变任何东西。
  • 我尝试使用命令execshell_execsystem

但是,如果我运行

if (exec('echo TEST') == 'TEST')
{
    echo 'exec works!';
}

它工作得很好,而shutdown now什么都不做。

PHP 具有访问和执行该文件的权限。

编辑:感谢亚历杭德罗,我能够解决问题。如果您有同样的问题,请不要忘记您的网络服务器可能/希望不会以 root 身份运行。尝试以 Web 服务器的用户或具有类似权限的用户身份登录,并尝试自己运行命令。

在 Ubuntu Server 10.04 上测试。我希望它在 Arch Linux 上也能帮助你。

在 PHP 中使用shell_exec函数:

通过 shell 执行命令,并以字符串形式返回完整的输出。

如果出现错误,它返回执行的命令或 NULL 的输出发生或命令不产生任何输出。

<?php 
$command = escapeshellcmd('/usr/custom/test.py');
$output = shell_exec($command);
echo $output;
?>

在 Python 文件test.py中,在第一行验证此文本:(见 shebang 解释):

#!/usr/bin/env python

如果你安装了多个版本的 Python,/usr/bin/env 将确保使用的解释器是环境中的第一个$PATH。另一种方法是硬编码类似的东西#!/usr/bin/python;没关系,但不太灵活。

在Unix中,要解释的可执行文件可以指示使用什么解释器来使用#!在第一行的开头,后跟解释器(以及可能需要的任何标志)。

当然,如果您谈论的是其他平台,则此规则不会申请(但"社邦线"没有坏处,如果你有的话会有所帮助将该脚本复制到具有 Unix 基础的平台,例如 Linux,苹果等)。

这适用于在 Unix 中通过使其可执行来运行它的情况(chmod +x myscript.py),然后直接运行它:./myscript.py,而不仅仅是蟒蛇 myscript.py

要在 unix 类型的平台上使文件可执行,请执行以下操作:

chmod +x myscript.py

此外,Python文件必须具有正确的权限(如果PHP脚本在浏览器或curl中运行,则为用户www-data/apache执行)和/或必须是"可执行的"。此外,.py文件中的所有命令都必须具有正确的权限。

摘自 php 手册:

对于那些试图shell_exec在Unix类型的平台,似乎无法使其工作。PHP 执行方式为系统上的Web用户(通常是Apache的www),所以你需要确保 Web 用户有权访问任何文件或您尝试在 shell_exec 命令中使用的目录。其他明智的是,它似乎不会做任何事情。

我建议使用passthru并直接处理输出缓冲区:

ob_start();
passthru('/usr/bin/python2.7 /srv/http/assets/py/switch.py arg1 arg2');
$output = ob_get_clean(); 

如果你想知道命令的返回状态并获取整个stdout输出,你可以实际使用exec

$command = 'ls';
exec($command, $out, $status);

$out是所有行的数组。 $status是返回状态。对于调试非常有用。

如果您还想查看stderr输出,您可以使用proc_open播放,也可以简单地将2>&1添加到您的$command中。后者通常足以使事情正常工作,并且更快地"实施"。

根据情况阐明使用哪个命令

exec() - 执行外部程序

system() - 执行外部程序并显示输出

passthru() - 执行外部程序并显示原始输出

来源: http://php.net/manual/en/function.exec.php

亚历杭德罗钉住了它,为例外(Ubuntu 或 Debian)添加了澄清 - 我没有代表添加到答案本身:

苏多尔文件: sudo visudo

添加了异常: www-data ALL=(ALL) NOPASSWD: ALL

就我而言,我需要在www目录中创建一个名为 scripts 的新文件夹。在scripts内,我添加了一个名为 test.py 的新文件。

然后我用sudo chown www-data:root scriptssudo chown www-data:root test.py.

然后我转到新的scripts目录并使用sudo chmod +x test.py.

我的 test.py 文件看起来像这样。请注意不同的 Python 版本:

#!/usr/bin/env python3.5
print("Hello World!")

从 php 我现在这样做:

$message = exec("/var/www/scripts/test.py 2>&1");
print_r($message);

你应该看到:你好世界!

上述方法似乎很复杂。使用我的方法作为参考。

我有两个文件:

  • 跑.php

  • mkdir.py

在这里,我创建了一个包含GO按钮的HTML页面。每当您按下此按钮时,都会在您提到的路径目录中创建一个新文件夹。

跑.php

<html>
 <body>
  <head>
   <title>
     run
   </title>
  </head>
   <form method="post">
    <input type="submit" value="GO" name="GO">
   </form>
 </body>
</html>
<?php
	if(isset($_POST['GO']))
	{
		shell_exec("python /var/www/html/lab/mkdir.py");
		echo"success";
	}
?>

mkdir.py

#!/usr/bin/env python    
import os    
os.makedirs("thisfolder");

灵感来自亚历杭德罗·奎罗兹:

<?php 
$command = escapeshellcmd('python test.py');
$output = shell_exec($command);
echo $output;
?>

需要添加 Python,并且不需要路径。

这太微不足道了,但只是想帮助任何已经遵循亚历杭德罗的建议但遇到此错误的人:

sh:blabla.py:找不到命令

如果有人遇到该错误,则需要对 Alejandro 的 php 文件进行一些更改:

$command = escapeshellcmd('python blabla.py');

上述所有选项都会创建新的系统进程。这是一场表演噩梦。为此,我将PHP模块与对Python的"透明"调用拼接在一起。

https://github.com/kirmorozov/runpy

编译起来可能很棘手,但可以节省系统进程,并允许您在PHP调用之间保持Python运行时。

我确实从上面的答案中找到了一些帮助。对我来说,python文件没有被调用,因为我正在一些旧版本的服务器上工作,并且我已经创建了我正在工作的虚拟环境(具有所有必需的库)。所以我这样称呼它:

$command="/home/userName/venv/bin/python /var/www/html/foldername1/foldername2/test.py"." ".$arg1." ".$arg2." ".$arg2; ''pass argument if needed in arg1 etc.
chdir("/var/www/html/folder1/folder2/"); //Changed the directory to where my files were
$output=shell_exec($command); //Execute the command in this directory
chdir("to the original working directory");

希望这对某人有所帮助。

PS:由于我们在实验室中授权访问互联网,因此在服务器上单独运行这些文件(python脚本)时,它们被困在下载任何模块或给出SSL错误等之间,所以只需向服务器提供互联网访问权限,它就可以工作了。然后我从PHP调用它。谢谢