![](/img/trans.png)
[英]Python 'No module named …' when script is executed by php with shell_exec()
[英]Python Script Hangs When Called via PHP shell_exec()
我有一个使用shell_exec
从PHP调用的Python脚本,所有脚本工作正常,并且在Python脚本完成并且一切都按exepcted运行后,脚本又回到了PHP函数。
现在,我更改了Python脚本,使其包含一个上一级的类,该类创建了一个Web驱动程序,并将该驱动程序返回到通过对象调用该脚本的脚本,然后另一个函数关闭了作为参数传入的驱动程序。
由于设置了这个新类并添加了一个对象以使用chrome创建/关闭webdriver的驱动程序,因此Python脚本在完成后会挂起,并且永远不会将控制权交还给PHP脚本来完成处理。
我曾经看过php system()shell_exec()挂在浏览器上 ,也浏览了http://php.net/manual/it/function.shell-exec.php#106250 ,但没有运气。
我需要运行PHP脚本,然后传递给Python脚本,等待Python脚本完成,然后移回PHP脚本以完成处理。
所有这些过程都是从Run.php
的:
$reponse = shell_exec('python36 "script1.py" "https://www.example.com/" "23"');
目录结构
root_dir
python_dir
scripts_dir
Script1.py
Script2.py
Script3.py
Global.py
run.php
全局
import re
from selenium import webdriver
class Global:
def getDriver(self):
try:
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('headless')
chrome_options.add_argument('no-sandbox')
# Windows - Dev Environment
driver = webdriver.Chrome(executable_path='C:\chromedriver.exe', chrome_options=chrome_options)
# Linux - Prod Environment
#driver = webdriver.Chrome(chrome_options=chrome_options)
return driver
except Exception as e:
print('Error: ' + str(e.args[0]))
def closeDriver(self, driver):
try:
driver.close()
return None
except Exception as e:
print('Error: ' + str(e.args[0]))
scripts_dir
中的所有脚本都有不同的代码,具体取决于执行的任务,但是新的Global
对象对于所有脚本都是相同的,新的Global对象是对所有脚本的唯一更改,因为它们可以正常工作到目前为止,Python脚本已挂起。
Script1.py
import os, sys
ROOT_DIR = os.path.normpath(os.path.join(os.path.abspath(__file__), '../..'))
sys.path.insert(0, ROOT_DIR)
from Global import Global
globalObj = Global()
try:
# Load all items on page
driver = globalObj.getDriver()
driver.get(PARAMS[1])
#... code to create a JSON file and populate it.
# Close webdriver
globalObj.closeDriver(driver)
print('Completed Ref: ' + str(PARAMS[2]))
except Exception as e:
print('Error: ' + str(e.args[0]))
我没有在Python或PHP或任何其他日志中获得任何错误或警告,Python脚本运行并创建了应有的预期JSON文件,并且看起来一切正常,行print('Completed Ref: ' + str(PARAMS[2]))
当Python脚本挂起时, print('Completed Ref: ' + str(PARAMS[2]))
似乎没有打印出来。
在命令行上运行Script1.py
大约需要35秒才能成功完成。
如果我删除对getDriver
和closeDriver
的Global
类的调用,则脚本将运行并完成并返回PHP以继续处理。
Script1.py-更新
import os, sys
from selenium import webdriver
try:
# Load all items on page
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('headless')
chrome_options.add_argument('no-sandbox')
driver = webdriver.Chrome(executable_path='C:\chromedriver.exe', chrome_options=chrome_options)
driver.get(PARAMS[1])
#... code to create a JSON file and populate it.
# Close webdriver
driver.close()
print('Completed Ref: ' + str(PARAMS[2]))
except Exception as e:
print('Error: ' + str(e.args[0]))
该脚本在命令行中以及在使用上述示例的shell_exec
通过PHP执行时均运行良好,因此在创建对象并调用getDriver
或closeDriver
类时肯定缺少closeDriver
。
经过进一步测试后,我可以确认问题是由调用类Global
的script1.py
脚本引起的, script1.py
创建Webdriver并将其关闭,一旦我在script1.py
删除了这些调用,脚本就可以正常运行。
我试图把在sys.exit()
后globalObj.closeDriver()
我也试着del globalObj
在没有运气剧本的结尾。
我已将网络驱动程序从Chrome更改为Firefox和PhantomJS,其他驱动程序在Global类上也可以正常工作,看起来它可能与现阶段的Chrome驱动程序有关。
我正在使用Chrome 64.0.3282.186 (Official Build) (64-bit)
和Chromedriver 2.35
。
您可以在获取参数后尝试使用WebDriverWait,该参数要等到过程结束
myElem = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.NAME, 'name_of_element')))
*我正在使用firefox驱动程序。
看起来是driver.close()
是问题的原因。 您需要在.quit()
中使用.quit()
来结束chromedriver进程,否则该进程将不会终止,这就是Python脚本看起来好像挂着的原因。
从:
driver.close()
至:
driver.quit()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.