cPanel App runs on Python2 instead of Python3

Question:

I have a VPS Hosting in cPanel, and a Flask-App.
I followed the instructions of How to install WSGI Application in cPanel.

Everything is working fine, when I run the application using the terminal, but when I open the App URL, it shows the following error:

Traceback (most recent call last):
  File "/opt/cpanel/ea-ruby24/root/usr/share/passenger/helper-scripts/wsgi-loader.py", line 369, in <module>
    app_module = load_app()
  File "/opt/cpanel/ea-ruby24/root/usr/share/passenger/helper-scripts/wsgi-loader.py", line 76, in load_app
    return imp.load_source('passenger_wsgi', startup_file)
  File "/home/qsemh/Maidan/passenger_wsgi.py", line 8, in <module>
    wsgi = imp.load_source('wsgi', 'wsgi.py')
  File "wsgi.py", line 1, in <module>
    from flaskr import create_app
  File "/home/qsemh/Maidan/flaskr/__init__.py", line 133
    print(f"Validate {len(users)} Users At {current_time}")
                                                         ^
SyntaxError: invalid syntax

So I’ve decided to create a simpler app in order to detect the issue, the app is as following :

passenger_wsgi.py

#!/usr/bin/env python3
import sys
from flask import Flask

application = Flask(__name__)

application.route("/")
def index():
    return sys.version

When I run this simple Application Using the URL it shows the following as a respond :

2.7.5 (default, Apr 2 2020, 13:16:51) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]

even though I’ve used the shebang #!/usr/bin/env python3 at the start of the file, and when I run it using the terminal, it works as if it using python3.

I’ve tried changing the shebang to the following formats :

#!/usr/bin/python3

#!/usr/bin/env 'python3'

but they gave the same result.

What is the problem here, and How can I solve it?

Asked By: Ebra_1

||

Answers:

I’ve found the Correct approach to solve this issue;

Basically, I only needed to add the following lines at the beginning of my passenger_wsgi.py file :

import os
INTERP = "/usr/bin/python3"
if sys.executable != INTERP: os.execl(INTERP, INTERP, *sys.argv)

so the final result would be :

passenger_wsgi.py


#!/usr/bin/env python3
import sys
import os

# Solution
INTERP = "/usr/bin/python3"
if sys.executable != INTERP: os.execl(INTERP, INTERP, *sys.argv)

from flask import Flask

application = Flask(__name__)

application.route("/")
def index():
    return sys.version

and the respond is correctly as I intended in the first place:

3.6.8 (default, Apr  2 2020, 13:34:55) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
Answered By: Ebra_1

This answer might be for some cPanel users. My cPanel is using passenger and wsgi, and even though my cPanel Python application is set to use python 3.9. it was running 2.7.5. Worse, it set all the 2.7 folders in the path.

So I ended up with this helper script called from
passenger_wsgi.py. I’m moved all the code out of this file into an import because this file may get blown away and re-created in some cases. It’s not safe to rely on code in this file surviving. It’s an auto generated file.

Put set_python_environment.py file in the same directory as passenger_wsgi.py

set_python_environment.py

# -*- coding: UTF-8 -*-

# insert these lines into passenger_wsgi.py if that file is rebuilt:
# import set_python_environment
# set_python_environment.upgrade_python()

import sys
import os

def upgrade_python():
    try:
            python_interpreter = "/home/username/virtualenv/YourApplicationPath/3.9/bin/python3.9_bin"
        if sys.executable != python_interpreter: 
            print('switching from ' + sys.version + ' to ' + python_interpreter + '...')
    
            print('directory: ' + os.path.dirname(__file__))
            print('file: ' + __file__)
            print('arg 0: ' + sys.argv[0])
    
            # rebuild the env path variable
            print('old system path:n' + "n".join(str(x) for x in sys.path))
            print('n')
            for x in sys.path:
                sys.path.remove(x)
    
            sys.path.append('/opt/cpanel/ea-ruby24/root/usr/share/passenger/helper-scripts')
            # App 3956 output: /usr/lib/python2.7/site-packages/pyzor-1.0.0-py2.7.egg
            # App 3956 output: /usr/lib64/python27.zip
            # App 3956 output: /usr/lib64/python2.7
            sys.path.append('/home/username/virtualenv/YourApplicationPath/3.9/lib64/python3.9')
            # App 3956 output: /usr/lib64/python2.7/plat-linux2
            # App 3956 output: /usr/lib64/python2.7/lib-tk
            # App 3956 output: /usr/lib64/python2.7/lib-old
            # App 3956 output: /usr/lib64/python2.7/lib-dynload
            # App 3956 output: /home/username/.local/lib/python2.7/site-packages
            # App 3956 output: /usr/lib64/python2.7/site-packages
            sys.path.append('/home/username/virtualenv/YourApplicationPath/3.9/lib64/python3.9/site-packages')
            # App 3956 output: /usr/lib64/python2.7/site-packages/gtk-2.0
            # App 3956 output: /usr/lib/python2.7/site-packages
            sys.path.append('/home/username/virtualenv/YourApplicationPath/3.9/lib/python3.9/site-packages')
            sys.path.append('/home/username/virtualenv/YourApplicationPath/3.9/bin')
            print('new system path:n' + "n".join(str(x) for x in sys.path))
            print('n')
            
            os.execl(python_interpreter, python_interpreter, *sys.argv)
        else:
            print('...continuing with ' + sys.executable)

    except Exception as e:
        print(str(e))
        

Modified passenger_wsgi.py

# -*- coding: UTF-8 -*-

import sys
import os
import imp

import set_python_environment
set_python_environment.upgrade_python()

sys.path.insert(0, os.path.dirname(__file__))
wsgi = imp.load_source('wsgi', 'app.py')
application = wsgi.app
        

In order to get the right path, I typed whereis python in the ssh environment after running the source command given on the python application page, to find the location of all the python versions, and the one ending in bin turned out to be the one which actually works.

Answered By: toddmo
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.