Python Script Hangs When Called via PHP shell_exec()
I have a Python script that is called from PHP usingshell_exec
, all was working fine and the script came back to the PHP function after the Python script completed and everything was working as exepcted.
Now I have changed the Python script to include a class one level up from it that creates a web driver and returns the driver to the script that calls it via an object and then another function closes the driver that is passed in as a parameter.
Since setting up this new class and adding in an object to create/close a driver for webdriver using chrome the Python script hangs after completion and it never hands back control to the PHP script to finish processing.
I've had a look at php system() shell_exec() hangs the browser and also at http://php.net/manual/it/function.shell-exec.php#106250 with no luck.
I need the PHP script to run and then pass to the Python script, wait for the Python script to complete and hand back to the PHP script to finish processing.
All this process is kicked off fromRun.php
with:
$reponse = shell_exec('python36 "script1.py" "https://www.example.com/" "23"');
Directory Structure
root_dir
python_dir
scripts_dir
Script1.py
Script2.py
Script3.py
Global.py
run.php
Global.py
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]))
All the scripts in thescripts_dir
have different code in them depeneding on the task they are doing, but the newGlobal
object stuff is the same for all scripts, the new Global object is the only change made to all the scripts since they were working fine till now where the Python scripts hang.
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]))
There are no errors or warnings in Python or PHP or any other logs available to me, the Python scripts run and create the expected JSON files they should and all looks to be working normally, the lineprint('Completed Ref: ' + str(PARAMS[2]))
doesn't seem to print out when the Python script hangs.
RunningScript1.py
on the command line takes about 35 seconds to complete successfully.
Update - 27 Feb 2018
If I remove the calls to theGlobal
class togetDriver
andcloseDriver
then the script runs and completes and hands back to PHP to continue processing.
Script1.py - Update
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]))
The script runs fine in both command line and when executed via PHP usingshell_exec
using the above example, so there must be something I'm missing when it comes to creating an object and call thegetDriver
orcloseDriver
classes.
Update 2 - 27 Feb 2018
After further testing, I can confirm that the issue is being caused by thescript1.py
script calling the classGlobal
to create the webdriver and close it, once I remove these calls inscript1.py
the script runs fine.
I've tried putting insys.exit()
after theglobalObj.closeDriver()
, I've also trieddel globalObj
at the end of the script with no luck.
Update 3 - 27 Feb 2018
I've changed out the webdriver from Chrome to Firefox and PhantomJS, Other drivers are working fine with the Global class, looking like it might be related to the Chrome driver at this stage.
I'm using Chrome64.0.3282.186 (Official Build) (64-bit)
and Chromedriver2.35
.
Answer
Solution:
you can try WebDriverWait after get params which wait till the end of the process
*i'm using firefox driver.
Answer
Solution:
It looks like
driver.close()
is the cause of the problem. You need to use.quit()
with Chromedriver to end the chromedriver process otherwise the process will not terminate which is why the Python script looked like it was hanging.From:
To: