Python Script Hangs When Called via PHP shell_exec()

721

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.

684

Answer

Solution:

you can try WebDriverWait after get params which wait till the end of the process

myElem = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.NAME, 'name_of_element')))

*i'm using firefox driver.

950

Answer

Solution:

It looks likedriver.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:

driver.close()

To:

driver.quit()

People are also looking for solutions to the problem: php - jQuery toggle function stops working after AJAX HTML data load

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.