如何在PHP中調(diào)用Python并獲取運(yùn)行結(jié)果
前言
在畢設(shè)中需要用到PHP
傳遞參數(shù)調(diào)用Python
腳本并獲取后者返回的結(jié)果,經(jīng)過(guò)查閱資料該問(wèn)題得以解決。
思路
PHP
借助shell_exec
通過(guò)類似于python sum.py $aa $bb
的形式以執(zhí)行系統(tǒng)命令的方式傳遞參數(shù)給Python
文件;
Python
則通過(guò)sys.argv
(需引入sys
模塊)來(lái)接收命令中所包含的參數(shù)(需要注意的是:此時(shí)傳入的參數(shù)都會(huì)被默認(rèn)為str
類型,需要在函數(shù)內(nèi)部進(jìn)行解析和轉(zhuǎn)換)并將處理結(jié)果通過(guò)print
函數(shù)輸出;
PHP
通過(guò)將shell_exec
函數(shù)返回的結(jié)果賦給變量實(shí)現(xiàn)取得Python
返回?cái)?shù)據(jù)的效果。
代碼
PHP
:
<form action="" method="post"> 請(qǐng)輸入a:<input type="number" name="a" value="請(qǐng)輸入a"><br> 請(qǐng)輸入b: <input type="number" name="b" value="請(qǐng)輸入b"> <button type="submit">計(jì)算</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] # 接收位置參數(shù) print(int(a)+int(b))
效果
補(bǔ)充
Python
:
除了sys.argv
,Python
還可以通過(guò)argparse
、tf.app.run
獲取傳入?yún)?shù)。
相對(duì)于sys.argv
,argparse
和tf.app.run
可以認(rèn)為是基于參數(shù)名稱的傳入
(前者是基于位置的參數(shù)傳入
)。
后者的具體使用方法記錄如下:
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
模塊,在函數(shù)內(nèi)定義好相關(guān)的命名參數(shù)(包括名稱、數(shù)據(jù)類型和默認(rèn)值等),從而在命令行中可以方便的調(diào)用。
需要注意的是,腳本運(yùn)行命令python script.py -gpus=0,1,2 --batch-size=10
中的--batch-size
會(huì)被自動(dòng)解析成batch_size
.parser.add_argument
方法的type
參數(shù)理論上可以是任何合法的類型, 但有些參數(shù)傳入格式比較麻煩,例如list
,所以一般使用bool
, int
, str
, float
這些基本類型就行了,更復(fù)雜的需求可以通過(guò)str
傳入,然后手動(dòng)解析。bool
類型的解析比較特殊,傳入任何值都會(huì)被解析成True
,傳入空值時(shí)才為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 # 返回結(jié)果7.0
總結(jié):通過(guò)這個(gè)方法還能指定命令的幫助信息。具體請(qǐng)看API
文檔:https://docs.python.org/2/library/argparse.html
通過(guò)這個(gè)方法還能指定命令的幫助信息。具體請(qǐng)看API
文檔:https://docs.python.org/2/library/argparse.html
tf.app.run
tensorflow
也提供了一種方便的解析方式。
腳本的執(zhí)行命令為:
python script.py -gpus=0,1,2 --batch_size=10
對(duì)應(yīng)的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()
有幾點(diǎn)需要注意:
tensorflow
只提供以下幾種方法:
tf.app.flags.DEFINE_string
,tf.app.flags.DEFINE_integer
,tf.app.flags.DEFINE_boolean
,
tf.app.flags.DEFINE_float
四種方法,分別對(duì)應(yīng)str
, int
,bool
,float
類型的參數(shù)。這里對(duì)bool
的解析比較嚴(yán)格,傳入1
會(huì)被解析成True
,其余任何值都會(huì)被解析成False
。
腳本中需要定義一個(gè)接收一個(gè)參數(shù)的main
方法:def main(_):
,這個(gè)傳入的參數(shù)是腳本名,一般用不到, 所以用下劃線接收。
以batch_size
參數(shù)為例,傳入這個(gè)參數(shù)時(shí)使用的名稱為--batch_size
,也就是說(shuō),中劃線不會(huì)像在argparse
中一樣被解析成下劃線。
tf.app.run()
會(huì)尋找并執(zhí)行入口腳本的main
方法。也只有在執(zhí)行了tf.app.run()
之后才能從FLAGS
中取出參數(shù)。
從它的簽名來(lái)看,它也是可以自己指定需要執(zhí)行的方法的,不一定非得叫main
:
run( main=None, argv=None )
tf.app.flags
只是對(duì)argpars
的簡(jiǎn)單封裝。
代碼:
# 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()
函數(shù)調(diào)用系統(tǒng)命令,
它們四者的區(qū)別如下:
shell_exec()
通過(guò) shell
環(huán)境執(zhí)行命令,并且將完整的輸出以字符串的方式返回。
也就是說(shuō), PHP
先運(yùn)行一個(gè)shell
環(huán)境, 然后讓shell
進(jìn)程運(yùn)行你的命令, 并且把所有輸出以字符串形式返回, 如果程序執(zhí)行有錯(cuò)誤或者程序沒(méi)有任何輸出, 則返回null
.
exec()
string exec ( string $command [, array &$output [, int &$return_var ]] )
與 shell_exec()
不一樣, exec
不會(huì)創(chuàng)建shell
進(jìn)程, 可以理解是php
進(jìn)程直接創(chuàng)建一個(gè)子進(jìn)程, 運(yùn)行指定的命令, 返回值只返回命令的最后一行, 所有的返回以參數(shù)形式返回, 上面的 $output
, 進(jìn)程的退出代碼以另外一個(gè)參數(shù)變量返回, 上面的 $return_var
passthru()
void passthru ( string $command [, int &$return_var ] )
與 exec()
類似, 唯一不同的是, 命令的所有輸出返回內(nèi)容都不再導(dǎo)入到 PHP
環(huán)境, 而是直接作為輸出內(nèi)容, 返回到瀏覽器的輸出上, 等效是把所有返回內(nèi)容直接 echo
輸出.
system()
這個(gè)方法和 passthru()
類似, 但是 system()
方法會(huì)在程序的每行輸出的時(shí)候執(zhí)行一次緩存輸出動(dòng)作, 可以理解為, 只要外部程序輸出一行, php
就會(huì)馬上把內(nèi)容推送到瀏覽器, 無(wú)論這個(gè)內(nèi)容是否足夠大. php
通常為了輸出效率, 都會(huì)有一個(gè)輸出緩存, 會(huì)等到輸出內(nèi)容足夠大之后, 再一次輸出返回. system()
方法則強(qiáng)制輸出內(nèi)容立刻推送, 即使輸出的內(nèi)容只有一個(gè)字母. 如果客戶端具有實(shí)時(shí)打印服務(wù)器的返回 http
內(nèi)容流的能力, 就可以看到 system()
的實(shí)時(shí)推送效果.
到此這篇關(guān)于如何在PHP中調(diào)用Python并獲取運(yùn)行結(jié)果的文章就介紹到這了,更多相關(guān)PHP調(diào)用Python獲取結(jié)果內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
php設(shè)計(jì)模式之策略模式應(yīng)用案例詳解
這篇文章主要介紹了php設(shè)計(jì)模式之策略模式,結(jié)合具體應(yīng)用案例形式詳細(xì)分析了php策略模式的原理、定義、實(shí)現(xiàn)方法及項(xiàng)目應(yīng)用案例與操作注意事項(xiàng),需要的朋友可以參考下2019-06-06php中3種方法統(tǒng)計(jì)字符串中每種字符的個(gè)數(shù)并排序
3種方法,統(tǒng)計(jì)字符串中每種字符的個(gè)數(shù)并排序,多種解法喲~ str_split()函數(shù)很重要2012-08-08php讀取二進(jìn)制流(C語(yǔ)言結(jié)構(gòu)體struct數(shù)據(jù)文件)的深入解析
本篇文章是對(duì)php讀取二進(jìn)制流(C語(yǔ)言結(jié)構(gòu)體struct數(shù)據(jù)文件)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06php抽獎(jiǎng)概率算法(刮刮卡,大轉(zhuǎn)盤)
這篇文章主要為大家詳細(xì)介紹了php中獎(jiǎng)概率算法,可用于刮刮卡,大轉(zhuǎn)盤等抽獎(jiǎng)算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-06-06PHP調(diào)用Linux命令權(quán)限不足問(wèn)題解決方法
這篇文章主要介紹了PHP調(diào)用Linux命令權(quán)限不足問(wèn)題解決方法,本文是解決項(xiàng)目問(wèn)題總結(jié)而來(lái),通過(guò)修改sudo配置文件解決無(wú)權(quán)限執(zhí)行命令問(wèn)題,需要的朋友可以參考下2015-02-02PHP中文豎排轉(zhuǎn)換實(shí)現(xiàn)方法
這篇文章主要介紹了PHP中文豎排轉(zhuǎn)換實(shí)現(xiàn)方法,一般大家的閱讀習(xí)慣是一行行瀏覽,很少使用豎排進(jìn)行閱讀,本文介紹了PHP實(shí)現(xiàn)中文豎排轉(zhuǎn)換,感興趣的小伙伴們可以參考一下2015-10-10php 函數(shù)中靜態(tài)變量使用的問(wèn)題實(shí)例分析
這篇文章主要介紹了php 函數(shù)中靜態(tài)變量使用的問(wèn)題,結(jié)合實(shí)例形式分析了php 函數(shù)中靜態(tài)變量使用過(guò)程中遇到的問(wèn)題,以及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2020-03-03