简体   繁体   中英

Flask App using wrong Python interpreter - need to know how to "compile" mod_wsgi to work with specific Python version

TL;DR , I need to know how to "compile" a WSGI file in such a way that it uses a different Python interpreter than when I initially installed mod_wsgi.

This is my first Flask app/website, so hopefully you can forgive a little bit of ignorance. I'll try to give you the relevant details.

I have a Flask app running on a Ubuntu server via Nginx/Apache (reverse proxy setup). My folder structure is like this:

|----MyApp
|------MyApp.wsgi
|------MyApp
|--------__init__.py
|--------templates
|--------static
|--------requirements.txt
|--------venv

I was getting weird exceptions thrown from my app, and discovered my Flask app was running the wrong version of the Python interpreter, thus some of the code wasn't working as expected. I have pyenv installed, and Python 3.8.1 set as global, but when the app runs through Apache, it's using Python 2.7.17 (the version that comes with Ubuntu 18.04). I figured out at least part of the problem. I was following along with this tutorial: https://www.digitalocean.com/community/tutorials/how-to-deploy-a-flask-application-on-an-ubuntu-vps

At one point, the tutorial has you do sudo pip install Flask , which seems to install Flask "globally" (ie, outside of the venv, which seems to defeat the purpose). Not sure if i'm using the correct terminology. So I had been doing:

python3 -m venv venv
source venv/bin/activate
sudo pip install Flask

Then when I would run my app, either through Apache, or even just from a terminal window, i'd print to a.txt file the sys.version , so I could see the Python interpreter it was using, and voila, it's using 2.7.17, not 3.8.1. So by trial and error, I learned that sudo pip install Flask wasn't what I wanted. pip install Flask (when run with my venv activated) produces the result I want when I run my Flask app from the terminal:

source venv/bin/activate
export FLASK_APP=__init__.py
flask run

And BAM, I get the correct version of Python, 3.8.1. However, now I have a new problem. When I restart Apache and try to go to my website, Apache gives the following error: Exception occurred processing WSGI script '/var/www/MyApp/MyApp.wsgi' and ImportError: No module named flask

I think I need to tell Apache or WSGI (or whoever) where my Flask installation is, since it is only installed within the venv. I found this SO post: Flask - WSGI - No module named 'flask'

And tried the suggested solution, using the python-path directive in my Apache config, like so:

  WSGIScriptAlias / /var/www/MyApp/MyApp.wsgi
  # WSGIDaemonProcess MyApp python-home=/var/www/MyApp/MyApp/venv
  WSGIDaemonProcess MyApp python-path=/var/www/MyApp:/var/www/MyApp/MyApp/venv/lib/python3.8/site-packages
  WSGIProcessGroup MyApp

And BAM, my app works again, but HEY why is it using Python 2.7.17 still? I followed the link that one of the commenters posted, regarding the use of virtual environments with WSGI: https://modwsgi.readthedocs.io/en/develop/user-guides/virtual-environments.html

From what I gathered, I must've installed mod_wsgi before installing pyenv and Python 3.8.1. So mod_wsgi is "compiled" with an old version of Python, and you can't use a virtual environment to force mod_wsgi to use a different python version than the one it was installed/compiled with. How do I reinstall and compile mod_wsgi so that it works off of my preferred Python version?

Edit: I tried doing

sudo apt-get --purge remove libapache2-mod-wsgi
sudo apt-get install libapache2-mod-wsgi-py3

However, now my app uses Python 3.6.9 (system version that came with Ubuntu 18.04). So it appears this method of installation ignores my pyenv settings (Python 3.8.1). Am I able to override this and specify a python version somehow?

After much googling, trial and error, and self-loathing, I figured it out. I tried many different ways of installing mod_wsgi that didn't work. I found a StackOverflow post that showed me one of the gotchas that was standing in my way, which was that I had not installed python 3.8.1 using pyenv with the shared libraries option set: Run mod_wsgi with pyenv

So I did:

pyenv uninstall 3.8.1
CONFIGURE_OPTS=--enable-shared pyenv install 3.8.1

Then I was able to activate my virtual environment, and install mod_wsgi locally to my app.

rm -rf venv
python3 -m venv venv
source venv/bin/activate
pip install Flask
pip install mod_wsgi

Then I had to tell apache which wsgi file to use. Luckily, there's a command you can run to show what to tell Apache:

mod_wsgi-express module-config

Which outputs something like this:

LoadModule wsgi_module "/var/www/MyApp/MyApp/venv/lib/python3.8/site-packages/mod_wsgi/server/mod_wsgi-py38.cpython-38-x86_64-linux-gnu.so"
WSGIPythonHome "/var/www/MyApp/MyApp/venv"

And I slapped that into the file: /etc/apache2/mods-available/wsgi.load

Restart apache, and SHAZAM. My app/website is running on Python 3.8.1!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM