前言
在毕设中需要用到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.argv
,Python
还可以通过argparse
、tf.app.run
获取传入参数。
相对于sys.argv
,argparse
和tf.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
,所以一般使用bool
, int
, str
, float
这些基本类型就行了,更复杂的需求可以通过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:
python script.py --a=4.0 --b=3.0 # 另一种写法: python script.py --a 4.0 --b 3.0 # 返回结果7.0
总结:通过这个方法还能指定命令的帮助信息。具体请看API
文档:https://docs.python.org/2/library/argparse.html
通过这个方法还能指定命令的帮助信息。具体请看API
文档:https://docs.python.org/2/library/argparse.html
tf.app.run
tensorflow
也提供了一种方便的解析方式。
脚本的执行命令为:
python script.py -gpus=0,1,2 --batch_size=10
对应的python代码为:
import tensorflow as tf tf.app.flags.DEFINE_string('gpus', None, 'gpus to use') tf.app.flags.DEFINE_integer('batch_size', 5, 'batch size') FLAGS = tf.app.flags.FLAGS def main(_): print FLAGS.gpus print FLAGS.batch_size if __name__=="__main__": tf.app.run()
有几点需要注意:
tensorflow
只提供以下几种方法:
tf.app.flags.DEFINE_string
,tf.app.flags.DEFINE_integer
,tf.app.flags.DEFINE_boolean
,
tf.app.flags.DEFINE_float
四种方法,分别对应str
, int
,bool
,float
类型的参数。这里对bool
的解析比较严格,传入1
会被解析成True
,其余任何值都会被解析成False
。
脚本中需要定义一个接收一个参数的main
方法:def main(_):
,这个传入的参数是脚本名,一般用不到, 所以用下划线接收。
以batch_size
参数为例,传入这个参数时使用的名称为--batch_size
,也就是说,中划线不会像在argparse
中一样被解析成下划线。
tf.app.run()
会寻找并执行入口脚本的main
方法。也只有在执行了tf.app.run()
之后才能从FLAGS
中取出参数。
从它的签名来看,它也是可以自己指定需要执行的方法的,不一定非得叫main
:
run( main=None, argv=None )
tf.app.flags
只是对argpars
的简单封装。
代码:
# Copyright 2015 The TensorFlow Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== """Implementation of the flags interface.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function import argparse as _argparse from tensorflow.python.util.all_util import remove_undocumented _global_parser = _argparse.ArgumentParser() # pylint: disable=invalid-name class _FlagValues(object): """Global container and accessor for flags and their values.""" def __init__(self): self.__dict__['__flags'] = {} self.__dict__['__parsed'] = False def _parse_flags(self, args=None): result, unparsed = _global_parser.parse_known_args(args=args) for flag_name, val in vars(result).items(): self.__dict__['__flags'][flag_name] = val self.__dict__['__parsed'] = True return unparsed def __getattr__(self, name): """Retrieves the 'value' attribute of the flag --name.""" if not self.__dict__['__parsed']: self._parse_flags() if name not in self.__dict__['__flags']: raise AttributeError(name) return self.__dict__['__flags'][name] def __setattr__(self, name, value): """Sets the 'value' attribute of the flag --name.""" if not self.__dict__['__parsed']: self._parse_flags() self.__dict__['__flags'][name] = value def _define_helper(flag_name, default_value, docstring, flagtype): """Registers 'flag_name' with 'default_value' and 'docstring'.""" _global_parser.add_argument('--' + flag_name, default=default_value, help=docstring, type=flagtype) # Provides the global object that can be used to access flags. FLAGS = _FlagValues() def DEFINE_string(flag_name, default_value, docstring): """Defines a flag of type 'string'. Args: flag_name: The name of the flag as a string. default_value: The default value the flag should take as a string. docstring: A helpful message explaining the use of the flag. """ _define_helper(flag_name, default_value, docstring, str) def DEFINE_integer(flag_name, default_value, docstring): """Defines a flag of type 'int'. Args: flag_name: The name of the flag as a string. default_value: The default value the flag should take as an int. docstring: A helpful message explaining the use of the flag. """ _define_helper(flag_name, default_value, docstring, int) def DEFINE_boolean(flag_name, default_value, docstring): """Defines a flag of type 'boolean'. Args: flag_name: The name of the flag as a string. default_value: The default value the flag should take as a boolean. docstring: A helpful message explaining the use of the flag. """ # Register a custom function for 'bool' so --flag=True works. def str2bool(v): return v.lower() in ('true', 't', '1') _global_parser.add_argument('--' + flag_name, nargs='?', const=True, help=docstring, default=default_value, type=str2bool) # Add negated version, stay consistent with argparse with regard to # dashes in flag names. _global_parser.add_argument('--no' + flag_name, action='store_false', dest=flag_name.replace('-', '_')) # The internal google library defines the following alias, so we match # the API for consistency. DEFINE_bool = DEFINE_boolean # pylint: disable=invalid-name def DEFINE_float(flag_name, default_value, docstring): """Defines a flag of type 'float'. Args: flag_name: The name of the flag as a string. default_value: The default value the flag should take as a float. docstring: A helpful message explaining the use of the flag. """ _define_helper(flag_name, default_value, docstring, float) _allowed_symbols = [ # We rely on gflags documentation. 'DEFINE_bool', 'DEFINE_boolean', 'DEFINE_float', 'DEFINE_integer', 'DEFINE_string', 'FLAGS', ] remove_undocumented(__name__, _allowed_symbols)
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()
的实时推送效果.
已有1位网友发表了看法: