1

尝试使用 mod_wsgi 和 virtualenv 部署 Django 1.4 项目时,我遇到了 500。Apache error_log 显示:

mod_wsgi (pid=30452): Exception occurred processing WSGI script '/path/to/project/site-packages/projectapp/wsgi.py'.
[...] Traceback (most recent call last):
[...]   File "/path/to/project/env/myenv/lib/python2.6/site-packages/django/core/handlers/wsgi.py", line 219, in __call__
[...]     self.load_middleware()
[...]   File "/path/to/project/env/myenv/lib/python2.6/site-packages/django/core/handlers/base.py", line 47, in load_middleware
[...]     raise exceptions.ImproperlyConfigured('Error importing middleware %s: "%s"' % (mw_module, e))
[...] ImproperlyConfigured: Error importing middleware projectapp.content.middleware: "cannot import name SomeModel"

从错误消息中,我预计这是某种路径问题。但是,当从 Django 设置中删除有问题的中间件时,站点启动正常,并且在这种情况下还会加载从projectapp.content,加载的其他模块SomeModel,否则整个站点将无法运行。

引发的导入错误并非直接来自中间件,因为它不导入模型。SomeModel在一个单独的应用程序中定义,该应用程序实际上已检出到 virtualenv 的 src 目录中。但包含此应用程序的目录也在路径中。

我正在使用的 wsgi.py 文件:

import os
import sys

sys.stdout = sys.stderr

sys.path.insert(0, '/path/to/project/env/myenv/lib/python2.6/site-packages/')
# The module inside the following directory
# defines SomeModel from the error message
sys.path.insert(0, '/path/to/project/env/myenv/src/some-app/')
sys.path.insert(0, '/path/to/project/site-packages/')

import django.core.handlers.wsgi

os.environ['DJANGO_SETTINGS_MODULE'] = 'projectapp.settings'
application = django.core.handlers.wsgi.WSGIHandler()

sys.path插入模块路径后的打印按预期顺序显示所有内容,/path/to/project/site-packages/首先列出,/path/to/project/env/myenv/src/some-app/(定义SomeModel)第二。

根据 mod_wsgi 文档中的示例,我还尝试了不同的变体:

import os
import sys
import site

ALLDIRS = [
    '/path/to/project/site-packages/',
    '/path/to/project/env/myenv/lib/python2.6/site-packages/',
    '/path/to/project/env/myenv/src/some-app/',
]

# Remember original sys.path
prev_sys_path = list(sys.path)

sys.stdout = sys.stderr

# Add each new site-packages directory
for directory in ALLDIRS:
    site.addsitedir(directory)

# Reorder sys.path so new directories are at the front
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

#activate_this = '/path/to/project/env/myenv/bin/activate_this.py'
#execfile(activate_this, dict(__file__=activate_this))

import django.core.handlers.wsgi

os.environ['DJANGO_SETTINGS_MODULE'] = 'projectapp.settings'
application = django.core.handlers.wsgi.WSGIHandler()

Apache 记录的错误是完全相同的。

我必须补充一点,当我在同一台机器上运行开发服务器时,中间件加载得很好,所以我不知道出了什么问题。有没有办法从 mod_wsgi 获得更好的回溯?

编辑:

忘记提及我在守护进程模式下使用 mod_wsgi 。以下是我的虚拟主机配置中的相关部分:

<VirtualHost x.x.x.x:80>
    WSGIDaemonProcess foo user=foo threads=10 umask=0002
    WSGIProcessGroup foo
    WSGIScriptAlias / /path/to/project/site-packages/projectapp/wsgi.py
</VirtualHost>
4

1 回答 1

0

好的,经过数小时的调试,结果证明这是由中间件引起的竞争条件。我使用的中间件与FlatpageFallbackMiddleware来自 Django contrib 的中间件类似,实际上是视图的导入导致了问题。

from projectapp.content.views import generic_content_detail
class ContentFallbackMiddleware(object):
    def process_response(self, request, response):
        [...]

在方法中移动 import 语句process_response为我解决了这个问题:

class ContentFallbackMiddleware(object):
    def process_response(self, request, response):
        from projectapp.content.views import generic_content_detail
        [...]
于 2012-09-14T14:31:35.877 回答