使用virtualenv运行mod_wsgi或不同于系统默认版本的Python

13

我正在尝试在CentOS服务器上运行我的Flask应用程序。基本问题是我已经安装了Python 2.6在/usr/bin里,这是系统默认的,同时也已经安装了Python 3.4在/usr/local/bin里。我想使用Python 3.4的虚拟环境或至少Python 3.4解释器来运行我的应用程序。

我已经在~/virtualenvs/flask创建了虚拟环境。

我有这个WSGI脚本:

import os
import sys
from logging import Formatter, FileHandler

APP_HOME = r"/home/fenikso/Album"


activate_this = os.path.join("/home/fenikso/virtualenvs/flask/bin/activate_this.py")
execfile(activate_this, dict(__file__=activate_this))

sys.path.insert(0, APP_HOME)
os.chdir(APP_HOME)

from app import app

handler = FileHandler("app.log")
handler.setFormatter(Formatter("[%(asctime)s | %(levelname)s] %(message)s"))
app.logger.addHandler(handler)
application = app

并在Apache中按照以下配置:

<VirtualHost *:80>
        ServerName album2.site.cz
        Alias /static "/home/fenikso/Album/static"
        Alias /photos "/home/fenikso/Album/photos"
        Alias /thumbs "/home/fenikso/Album/thumbs"
        WSGIScriptAlias / "/home/fenikso/Album/wsgi.py"
        <Directory "/home/fenikso/Album">
            AllowOverride None
            Allow from all
        </Directory>
        <Directory "/home/fenikso/Album/static">
            AllowOverride None
            Allow from all
        </Directory>
        <Directory "/home/fenikso/Album/photos">
            AllowOverride None
            Allow from all
        </Directory>
        <Directory "/home/fenikso/Album/thumbs">
            AllowOverride None
            Allow from all
        </Directory>
</VirtualHost>

然而,当我尝试运行应用程序时,我遇到了一个错误:

Apache/2.2.15 (Unix) DAV/2 mod_wsgi/3.2 Python/2.6.6 mod_fcgid/2.3.7 PHP/5.3.3 mod_ssl/2.2.15 OpenSSL/1.0.1e-fips SVN/1.6.11 mod_perl/2.0.4 Perl/v5.10.1 configured -- resuming normal operations
mod_wsgi (pid=14627): Target WSGI script '/home/fenikso/Album/wsgi.py' cannot be loaded as Python module.
mod_wsgi (pid=14627): Exception occurred processing WSGI script '/home/fenikso/Album/wsgi.py'.
Traceback (most recent call last):
   File "/home/fenikso/Album/wsgi.py", line 15, in <module>
     from app import app
   File "/home/fenikso/Album/app.py", line 1, in <module>
     from flask import Flask
 ImportError: No module named flask

我注意到要么是在运行Python 2.6,要么我的virtualenv没有被激活。有什么正确的方法可以使其正常工作并且仍然将Python 2.6作为系统默认版本?

4个回答

10
你需要在apache.conf中添加以下行,以便为可执行文件和虚拟环境的路径提供正确的设置。
WSGIPythonHome /usr/local/bin
WSGIPythonPath /home/fenikso/virtualenv/lib/python3.4/site-packages

这两个命令的所有选项都可以在mod_wsgi文档中找到。

请注意,您必须使用与Python可执行文件兼容的mod_wsgi版本。在您的情况下,您可能需要安装mod_wsgi3.4并配置apache使用它而不是标准mod_wsgi模块。

整个配置文件应如下所示:

WSGIPythonHome "/usr/local/bin"
WSGIPythonPath "/home/fenikso/virtualenv/lib/python3.4/site-packages"

<VirtualHost *:80>
        ServerName album2.site.cz
        Alias /static "/home/fenikso/Album/static"
        Alias /photos "/home/fenikso/Album/photos"
        Alias /thumbs "/home/fenikso/Album/thumbs"
        WSGIScriptAlias / "/home/fenikso/Album/wsgi.py"
        <Directory "/home/fenikso/Album">
            AllowOverride None
            Allow from all
        </Directory>
        <Directory "/home/fenikso/Album/static">
            AllowOverride None
            Allow from all
        </Directory>
        <Directory "/home/fenikso/Album/photos">
            AllowOverride None
            Allow from all
        </Directory>
        <Directory "/home/fenikso/Album/thumbs">
            AllowOverride None
            Allow from all
        </Directory>
</VirtualHost>

我认为这是正确的方法。然而,在我的环境中,我无法使其工作。太多的东西破碎和混乱了,所以我放弃了并尝试了另一种方式。 - Fenikso
然而,WSGIPythonHomeWSGIPythonPath不应该在<VirtualHost>之外吗? - Fenikso
2
你说得很对,这些选项必须在<VirtualHost>块之外。是我的错误。如果您必须为每个<VirtualHost>使用不同的virtualenv,则可以使用WSGIDaemonProcessWSGIProcessGroup指令,通过设置python-path选项。 - afrancais

2
查看WSGIPythonHome和WSGIPythonPath指令。可能你安装了一个python2.6的mod_wsgi,而mod_wsgi必须编译为所需的python版本,并且不支持多个python版本。因此,请确保您的mod_wsgi兼容py3.4并设置上述指令。
或者,您可以使用像gunicorn这样的python服务器运行flask应用程序,并从apache到gunicorn进行proxypass。

谢谢您的建议。我尝试了解WSGIPythonHome和WSGIPythonPath,但是由于没有找到任何示例,我不知道如何正确使用它们。另外,我该如何检查mod_wsgi的“类型”?我只是运行了yum install mod_wsgi - Fenikso
1
@Fenikso,@afrancais提供了一个更完整的使用指令的例子,请参考他的回答。您可以通过在库上执行ldd命令来检查编译的Python mod_wsgi版本,可能是ldd /usr/{lib,lib64}/httpd/modules/mod_wsgi.so - kalhartt
感谢提供关于ldd和建议使用Gunicorn的宝贵信息。最终我选择了uWSGI + Nginx。有帮助的是,uWSGI可以通过pip安装,因此我可以直接为所需的Python版本安装它。 - Fenikso

1
另一个选择是我认为更加清晰,逻辑性更强,灵活性更大的方法:在您的WSGI文件开头直接引用venv中的Python解释器。这样做很容易更改(无需繁琐地操作系统配置文件),并且还可以打开多个应用程序以使用不同的Python环境的可能性,如下所示:
#!/path/to/your/venv/bin/python

0
如果系统上安装的Python版本与虚拟环境中使用的Python版本不同,则mod_wsgi将无法工作,因为mod_wsgi始终是针对特定的Python版本编译的。
在这种情况下,您需要在虚拟环境中安装mod_wsgi。
pip install mod_wsgi-standalone

那么应该加载这样的一个模块,而不是系统中安装的默认模块。

例如,在Ubuntu上,修改/etc/apache2/mods-available/wsgi.load中模块的路径。

LoadModule wsgi_module /home/user/etc/.venv/lib/python3.9/site-packages/mod_wsgi/server/mod_wsgi-py39.cpython-39-x86_64-linux-gnu.so

为了避免错误 "no such file or directory: mod_wsgi (pid=XXXX): Couldn't bind unix domain socket '/usr/local/opt/httpd/logs/wsgi.xxxxx.11.1.sock",应将其添加到httpd.conf文件中:

WSGISocketPrefix /var/run/wsgi

重启 Apache 后一切应该正常工作


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接