FlaskApp在Apache与mod_wsgi中返回HTTP 500

3 投票
4 回答
2633 浏览
提问于 2025-04-18 05:06

我正在尝试通过Apache和mod_wsgi来托管我的Python 3.4的Flask应用。通过Flask自带的服务器运行这个应用是没问题的。这个应用是在一个虚拟环境中创建的,使用的是pyvenv-3.4。

但是,当我试图在浏览器中连接到Apache服务器时,出现了500 HTTP错误。配置文件和日志已经附上。我觉得这可能和使用pyvenv而不是通过pip安装的virtualenv有关。Flask的文档告诉我用以下命令来激活虚拟环境:

activate_this = '/path/to/env/bin/activate_this.py'

然而,这个命令会产生一个IOError,因为文件不存在。我尝试把它指向'activate'文件,还有activate.csh和activate.fish,但都没有成功。所有这些文件在deactivate那一行都会产生SyntaxError。

我该如何通过Apache运行这个应用,并使用我的virtualenv呢?

flaskapp.wsgi

#!/usr/bin/python
activate_this = '/var/www/FlaskApp/FlaskApp/bin/activate'
execfile(activate_this, dict(__file__=activate_this))
import sys
import logging

logging.basicConfig(stream=sys.stderr)
sys.path.insert(0,"/var/www/FlaskApp/")

from FlaskApp import app as application
application.secret_key = 'some secret key'

Apache VirtualHost

<VirtualHost *:80>
            ServerName example.org # my server name
            ServerAlias gallifrey 192.168.0.84
            ServerAdmin admin@example.org # my admin
            WSGIScriptAlias /flask /var/www/FlaskApp/flaskapp.wsgi
            <Directory /var/www/FlaskApp/FlaskApp/>
                    Order allow,deny
                    Allow from all
            </Directory>
            Alias /static /var/www/FlaskApp/FlaskApp/static
            <Directory /var/www/FlaskApp/FlaskApp/static/>
                    Order allow,deny
                    Allow from all
            </Directory>
            ErrorLog ${APACHE_LOG_DIR}/error.log
            LogLevel warn
            CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Hierarchy

/var/www/FlaskApp
  flaskapp.wsgi
  FlaskApp/
    bin/
      activate
      activate.csh
      activate.fish
      easy_install, easy_install-3.4
      pip, pip3, pip3.4
      python, python3, python3.4
    include/
    lib/
    scripts/
    static/
    templates/
    app.py
    __init__.py

尝试打开网页时,我得到了一个HTTP 500错误:

Apache error.log

[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81] mod_wsgi (pid=31629): Target WSGI script '/var/www/FlaskApp/flaskapp.wsgi' cannot be loaded as Python module.
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81] mod_wsgi (pid=31629): Exception occurred processing WSGI script '/var/www/FlaskApp/flaskapp.wsgi'.
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81] Traceback (most recent call last):
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81]   File "/var/www/FlaskApp/flaskapp.wsgi", line 3, in <module>
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81]     execfile(activate_this, dict(__file__=activate_this))
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81]   File "/var/www/FlaskApp/FlaskApp/bin/activate", line 4
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81]     deactivate () {
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81]                   ^
[Fri May 02 10:22:58 2014] [error] [client 192.168.0.81] SyntaxError: invalid syntax

4 个回答

0

我试着把这个代码加到 /etc/httpd/conf/httpd.conf 文件的上面和外面,结果成功了。

WSGIPythonPath /your_virtualenv/lib/python2.7/site-package
1

当你使用Python虚拟环境时,如果你在用像Django或Flask这样的应用程序,你需要确保Apache能找到WSGI的路径。

如果你使用的是Debian系统,并且通过包管理器安装了Apache,那么你的配置文件目录结构应该是这样的:/etc/apache2/。

接下来,你需要编辑一个虚拟主机的配置文件(比如说AppName.conf),这个文件在"/etc/apache2/sites-available/AppName.conf"下。然后可以参考下面的示例,来为一个使用Python 3.5的Flask应用进行配置:

WSGIPythonPath /<PATH_OF_PYTHON_VIRTUAL_ENVIRONMENT>/lib/python3.5/site-packages
<VirtualHost *:80>
        ServerName <HOST or IP_ADDRESS>
        ServerAdmin your-email@domain.com
        WSGIScriptAlias / /var/www/app_name/your_wsgi_app.wsgi
        WSGIPassAuthorization On
        <Directory /var/www/app_name/AppName/>
                Order allow,deny
                Allow from all
        </Directory>
        Alias /static /var/www/app_name/AppName/static
        <Directory /var/www/app_name/AppName/static/>
                Order allow,deny
                Allow from all
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/error.log
        # e.g. LogLevel debug
        LogLevel <info|warn|error|debug>
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
1

你试过这样做吗:

WSGIPythonHome /var/www/FlaskApp

然后让 mod_wsgi 来处理设置的事情,还是你自己来做?

1

你可以按照虚拟环境的说明来操作,或者你也可以模仿一下virtualenvactivate_this.py脚本是怎么做的:

import sys
import os

old_os_path = os.environ['PATH']
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + os.pathsep + old_os_path
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if sys.platform == 'win32':
    site_packages = os.path.join(base, 'Lib', 'site-packages')
else:
    site_packages = os.path.join(base, 'lib', 'python%s' % sys.version[:3], 'site-packages')
prev_sys_path = list(sys.path)
import site
site.addsitedir(site_packages)
sys.real_prefix = sys.prefix
sys.prefix = base
# Move the added items to the front of the path:
new_sys_path = []
for item in list(sys.path):
    if item not in prev_sys_path:
        new_sys_path.append(item)
        sys.path.remove(item)
sys.path[:0] = new_sys_path

你可以把这个做成一个更通用的函数:

import sys
import os

def activate_venv(path):
    if sys.platform == 'win32':
        bin_dir = os.path.join(path, 'Scripts')
        site_packages = os.path.join(base, 'Lib', 'site-packages')
    else:
        bin_dir = os.path.join(path, 'bin')
        site_packages = os.path.join(BASE, 'lib', 'python%s' % sys.version[:3], 'site-packages')
    os.environ['PATH'] = bin_dir + os.pathsep + os.environ['PATH']
    prev_sys_path = list(sys.path)
    import site
    site.addsitedir(site_packages)
    sys.prefix, sys.real_prefix = path, sys.prefix

    # Move the added items to the front of the path:
    new_sys_path = []
    for item in list(sys.path):
        if item not in prev_sys_path:
            new_sys_path.append(item)
            sys.path.remove(item)
    sys.path[:0] = new_sys_path

把这个放在你默认的Python模块搜索路径中的一个模块里,然后导入activate_venv,并传入os.path.dirname(os.path.abspath(__file__))的结果:

from somemodule import activate_venv
import os.path
activate_venv(os.path.dirname(os.path.abspath(__file__)))

撰写回答