如何在PHP中调用Python并获取运行结果

前言

在毕设中需要用到PHP传递参数调用Python脚本并获取后者返回的结果,经过查阅资料该问题得以解决。

思路

PHP借助shell_exec通过类似于python sum.py $aa $bb的形式以执行系统命令的方式传递参数给Python文件;

Python则通过sys.argv(需引入sys模块)来接收命令中所包含的参数(需要注意的是:此时传入的参数都会被默认为str类型,需要在函数内部进行解析和转换)并将处理结果通过print函数输出;

PHP通过将shell_exec函数返回的结果赋给变量实现取得Python返回数据的效果。

代码

PHP:

<form action="" method="post">
    请输入a:<input type="number" name="a" value="请输入a"><br> 请输入b:
    <input type="number" name="b" value="请输入b">
    <button type="submit">计算</button>
</form>
<?php
$aa = $_POST["a"];
$bb = $_POST["b"];
$cmd = shell_exec("python sum.py $aa $bb");
echo "a与b的和是: $cmd";
?>

Python:

import sys

a, b = sys.argv[1], sys.argv[2]   # 接收位置参数
print(int(a)+int(b))

效果

补充

Python:

除了sys.argvPython还可以通过argparsetf.app.run获取传入参数。

相对于sys.argvargparsetf.app.run可以认为是基于参数名称的传入(前者是基于位置的参数传入)。

后者的具体使用方法记录如下:

argparse

示例1:

import argparse
parser = argparse.ArgumentParser(description='manual to this script')
parser.add_argument('--gpus', type=str, default = None)
parser.add_argument('--batch-size', type=int, default=32)
args = parser.parse_args()
print args.gpus
print args.batch_size

利用argparse模块,在函数内定义好相关的命名参数(包括名称、数据类型和默认值等),从而在命令行中可以方便的调用。

需要注意的是,脚本运行命令python script.py -gpus=0,1,2 --batch-size=10中的--batch-size会被自动解析成batch_size.
parser.add_argument 方法的type参数理论上可以是任何合法的类型, 但有些参数传入格式比较麻烦,例如list,所以一般使用boolintstrfloat这些基本类型就行了,更复杂的需求可以通过str传入,然后手动解析。bool类型的解析比较特殊,传入任何值都会被解析成True,传入空值时才为False

python script.py --bool-val=0 # args.bool_val=True
python script.py --bool-val=False # args.bool_val=True
python script.py --bool-val=     # args.bool_val=什么都不写False

示例2:

Python:

import argparse

parser = argparse.ArgumentParser(description='a demo of script')
parser.add_argument('--a', type=float, default=0.0)  # 添加变量
parser.add_argument('--b', type=float, default=1.0)

if __name__ == '__main__':
    args = parser.parse_args()   # 解析所有的命令行传入变量
    add(args.a, args.b)

Shell:

总结:通过这个方法还能指定命令的帮助信息。具体请看API文档:https://docs.python.org/2/library/argparse.html

通过这个方法还能指定命令的帮助信息。具体请看API文档:https://docs.python.org/2/library/argparse.html

tf.app.run

tensorflow也提供了一种方便的解析方式。

脚本的执行命令为:

对应的python代码为:

有几点需要注意:

tensorflow提供以下几种方法:

  • tf.app.flags.DEFINE_string
  • tf.app.flags.DEFINE_integer,
  • tf.app.flags.DEFINE_boolean,

tf.app.flags.DEFINE_float 四种方法,分别对应strint,bool,float类型的参数。这里对bool的解析比较严格,传入1会被解析成True,其余任何值都会被解析成False

脚本中需要定义一个接收一个参数的main方法:def main(_):,这个传入的参数是脚本名,一般用不到, 所以用下划线接收。

batch_size参数为例,传入这个参数时使用的名称为--batch_size,也就是说,中划线不会像在argparse 中一样被解析成下划线。

tf.app.run()会寻找并执行入口脚本的main方法。也只有在执行了tf.app.run()之后才能从FLAGS中取出参数。

从它的签名来看,它也是可以自己指定需要执行的方法的,不一定非得叫main

tf.app.flags只是对argpars的简单封装。

代码:

PHP:

除了使用shell_exec(),还可以使用exec()passthru()system()函数调用系统命令,

它们四者的区别如下:

shell_exec()

通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
也就是说, PHP先运行一个shell环境, 然后让shell进程运行你的命令, 并且把所有输出以字符串形式返回, 如果程序执行有错误或者程序没有任何输出, 则返回null.

exec()

string exec ( string $command [, array &$output [, int &$return_var ]] )与 shell_exec() 不一样, exec不会创建shell进程, 可以理解是php进程直接创建一个子进程, 运行指定的命令, 返回值只返回命令的最后一行, 所有的返回以参数形式返回, 上面的 $output, 进程的退出代码以另外一个参数变量返回, 上面的 $return_var

passthru()

void passthru ( string $command [, int &$return_var ] )与 exec() 类似, 唯一不同的是, 命令的所有输出返回内容都不再导入到 PHP 环境, 而是直接作为输出内容, 返回到浏览器的输出上, 等效是把所有返回内容直接 echo 输出.

system()

这个方法和 passthru() 类似, 但是 system() 方法会在程序的每行输出的时候执行一次缓存输出动作, 可以理解为, 只要外部程序输出一行, php 就会马上把内容推送到浏览器, 无论这个内容是否足够大. php通常为了输出效率, 都会有一个输出缓存, 会等到输出内容足够大之后, 再一次输出返回. system() 方法则强制输出内容立刻推送, 即使输出的内容只有一个字母. 如果客户端具有实时打印服务器的返回 http 内容流的能力, 就可以看到 system() 的实时推送效果.