可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I've got a basic "hello world" Flask app running.
I'm on Ubuntu 14.04, using Apache 2.4. I've installed mod_wsgi.
I've created a ~/web/piFlask/venv/
to hold a virtualenv-created Python2 with flask installed.
However, I wish to have my flaskapp import a Python3.x module I have written.
What do I need to do to make this happen?
I tried creating a ~/web/piFlask/venv3/
and modifying ~/web/piFlask/piFlask.wsgi
:
import os, sys
PROJECT_DIR = '/home/pi/web/piFlask'
activate_this = os.path.join(PROJECT_DIR, 'venv3/bin', 'activate_this.py')
execfile(activate_this, dict(__file__=activate_this))
sys.path.insert(0, PROJECT_DIR)
from piFlask import app as application
application.debug = True
But I don't think this is sufficient. This .wsgi is in fact a Python file that will get executed by mod_wsgi, which I'm sure will use a Py2.x interpreter to do the execution.
So if I'm understanding correctly, mod_wsgi fires up the system Python in order to execute this .wsgi, which will in turn fire up my ~/web/piFlask/venv/
interpreter to actually process the request.
I think I could persuade mod_wsgi to use either a system Python3 or my own venv3/... by setting WSGIPythonPath /home/pi/web/piFlask/venv3/lib/python3.4/site-packages
in /etc/apache2/mods-available/wsgi.conf
But I found an instruction somewhere saying you have to compile mod_wsgi for Py3, and the bottom quickly falls out to this problem.
回答1:
Correct, mod_wsgi needs to be compiled for a specific Python version as it never actually executes 'python' executable. Instead the Python library is linked into mod_wsgi.
The end result is you cannot mix Python 3 code within an application running using the Python 2 interpreter.
You would have to consider making your code runnable under both Python 2 and 3 and then you could choose which of those you want to use and use a version of mod_wsgi compiled for the version you choose to use.
回答2:
Took me awhile, although it was really simple in the end. Unfortunately I've lost my bash history so if you find a mistake, please leave a comment or edit in the correction.
Note that I had already got mod_wsgi working, so I had to remove it:
$ a2dismod wsgi
$ sudo apt-get remove libapache2-mod-wsgi
EDIT: Due to apt-get installing an outdated package (which results in a minor error creeping into Apache's error log) I don't at time of writing recommend this:
$ sudo apt-get install libapache2-mod-wsgi-py3
$ a2enmod wsgi
Instead, first set up your py3 virtual environment, (and might as well in install Flask into it while you're at it)
$ pip install virtualenv
$ cd ~/web/flaskapp
$ virtualenv -p python3 ./venv3
$ source ./venv3/bin/activate # enter virtual environment
$ pip install Flask
Now follow Installing mod_wsgi for Python3 on Ubuntu to install mod_wsgi into this venv, and ...
$ deactivate # ... & exit
This was from the original apt-get approach, now it is not relevant:
Now I have to make mod_wsgi
use this new Py3:
$ sudo nano /etc/apache2/mods-enabled/wsgi.conf
And do:
#WSGIPythonPath directory|directory-1:directory-2:...
WSGIPythonPath /home/pi/web/flaskapp/venv3/lib/python3.4/site-packages
Finally I need to modify my ~/web/flaskapp/flaskapp.wsgi so that it now supports Python3:
$ cat web/piFlask/piFlask.wsgi
# http://flask.pocoo.org/docs/0.10/deploying/mod_wsgi/#creating-a-wsgi-file
# http://www.enigmeta.com/2012/08/16/starting-flask/
# for Py3:
# http://askubuntu.com/questions/488529/pyvenv-3-4-error-returned-non-zero-exit-status-1
import os, sys
PROJECT_DIR = '/home/pi/web/flaskapp'
sys.path.insert(0, PROJECT_DIR)
def execfile(filename):
globals = dict( __file__ = filename )
exec( open(filename).read(), globals )
activate_this = os.path.join( PROJECT_DIR, 'venv3/bin', 'activate_this.py' )
execfile( activate_this )
from piFlask import app as application
application.debug = True
Just a reminder of how Apache uses mod_wsgi to execute this file when the user points their browser to http://myfoo.org/flask:
$ cat /etc/apache2/sites-available/000-default.conf
:
WSGIDaemonProcess flaskProcess user=pi group=pi threads=5
WSGIScriptAlias /flask /home/pi/web/flaskapp/flaskapp.wsgi
<Location /flask>
WSGIProcessGroup flaskProcess
WSGIApplicationGroup %{GLOBAL}
Require all granted
</Location>
:
Discussion: It seems a bit messy that I am installing mod_wsgi module into Apache, but it resides in a venv3 which is inside my flaskapp folder. But this is at least ensuring Apache -> mod_wsgi -> (uses the correct i.e. venv3 Python) -> {to launch my FlaskApp}.
The alternative would be to update the system Python, and use that instead of venv.
回答3:
I started running python3.5.2 with flask 0.12 in a venv on a Ubuntu 16.04 (virtual machine).
@Graham pointed out activating the the venv from the WSGI script file is not the preferred way. More info here: http://modwsgi.readthedocs.io/en/develop/user-guides/virtual-environments.html
Just for anyone else looking for info on this I'm putting all your steps together:
Note: my app name is blazing, path ~/jan/blazing. Replace them with your own.
sudo apt install python3-pip
sudo apt-get install python3-venv
python3 -m venv ~/blazing/venv
source /home/jan/blazing/venv/bin/activate
pip3 install --upgrade pip
pip3 install Flask
sudo apt-get install apache2-dev
(venv) pip3 install mod_wsgi
(venv) sudo venv3/bin/mod_wsgi-express install-module
OUTPUT:
LoadModule wsgi_module "/usr/lib/apache2/modules/mod_wsgi-py35.cpython-35m-x86_64-linux-gnu.so"
WSGIPythonHome "/home/jan/blazing/venv"
sudo vim /etc/apache2/mods-available/wsgi_express.load
ADD: LoadModule wsgi_module "/usr/lib/apache2/modules/mod_wsgi-py35.cpython-35m-x86_64-linux-gnu.so"
sudo vim /etc/apache2/mods-available/wsgi_express.conf
ADD:
WSGIPythonHome "/home/jan/blazing/venv"
WSGIPythonPath /home/jan/blazing/venv/lib/python3.x/site-packages
then
sudo a2enmod wsgi_express
vim /home/jan/blazing/project/flaskapp.wsgi
ADD:
import os, sys
PROJECT_DIR = '/home/jan/blazing' sys.path.insert(0, PROJECT_DIR)
activate_this = os.path.join( PROJECT_DIR, 'venv/bin', 'activate_this.py' )
with open(activate_this) as file_:
exec(file_.read(), dict(__file__=activate_this)
from piFlask import app as application application.debug = True
and
vim /etc/apache2/sites-available/flask.conf
ADD:
WSGIDaemonProcess flaskProcess user=www-data group=www-data threads=5
WSGIScriptAlias /flask /home/jan/blazing/project/flaskapp.wsgi
ErrorLog ${APACHE_LOG_DIR}/error_flask.log #you can see the errors here..
CustomLog ${APACHE_LOG_DIR}/access_flask.log combined
<Location /flask>
WSGIProcessGroup flaskProcess
WSGIApplicationGroup %{GLOBAL}
Require all granted
</Location>
Or if you have other sites running and would like to have flask as one of the Virtual hosts, you can use this conf file:
<VirtualHost *>
ServerName flask.ubuntuws
ErrorLog ${APACHE_LOG_DIR}/error_flask.log
CustomLog ${APACHE_LOG_DIR}/access_flask.log combined
WSGIDaemonProcess flaskProcess user=www-data group=www-data threads=5
WSGIScriptAlias / /home/jan/blazing/project/flaskapp.wsgi
<Location />
WSGIProcessGroup flaskProcess
WSGIApplicationGroup %{GLOBAL}
Require all granted
</Location>
</VirtualHost>
and make sure your PROJECT_DIR
in flaskapp.wsgi
points to your PROJECT_NAME.py.
enable the virtual site and reload apache:
lastly:
sudo a2ensite flask.conf
sudo service apache2 reload
回答4:
Taken from the P i's answer. The following now works and fixes the problem:
$ sudo apt-get install libapache2-mod-wsgi-py3
$ a2enmod wsgi