You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache+mod_wsgi部署多Django项目加载错误模块问题求助

问题描述

在Windows服务器上通过Apache+mod_wsgi部署多个Django开发/测试项目,此前成功部署过多Flask项目。

项目结构

ProjectA(含认证/登录/登出功能)
  - appa1(共享模板/静态文件)
  - appa2
ProjectB 
  - appa1(共享模板/静态文件)
  - appb1
  - appb2
ProjectC
  - appa1(共享模板/静态文件)
  - appc1
  - appc2

Apache VirtualHost配置

<VirtualHost dev.projecta.mydomain.com:80>
    ServerName dev.projecta.mydomain.com
    Redirect / https://dev.projecta.mydomain.com
</VirtualHost>
<VirtualHost dev.projecta.mydomain.com:443>
    ServerName dev.projecta.mydomain.com
    WSGIScriptAlias / "C:/projecta/projecta.wsgi"
    CustomLog "logs/projecta_access.log" common
    ErrorLog "logs/projecta_error.log"
    SSLEngine on
    SSLCertificateFile "C:/path/to/projecta_cert/cert.cer"
    SSLCertificateKeyFile "C:/path/to/projecta_cert/project.key"
    <Directory C:\projecta>
        Require all granted
    </Directory>
</VirtualHost>
<VirtualHost dev.projectb.mydomain.com:80>
    ServerName dev.projectb.mydomain.com
    Redirect / https://dev.projectb.mydomain.com
</VirtualHost>
<VirtualHost dev.projectb.mydomain.com:443>
    ServerName dev.projectb.mydomain.com
    WSGIScriptAlias / "C:/projectb/projectb.wsgi"
    CustomLog "logs/projectb_access.log" common
    ErrorLog "logs/projectb_error.log"
    SSLEngine on
    SSLCertificateFile "C:/path/to/projectb_cert/cert.cer"
    SSLCertificateKeyFile "C:/path/to/projectb_cert/project.key"
    <Directory C:\projectb>
        Require all granted
    </Directory>
</VirtualHost>
<VirtualHost dev.projectc.mydomain.com:80>
    ServerName dev.projectc.mydomain.com
    Redirect / https://dev.projectc.mydomain.com
</VirtualHost>
<VirtualHost dev.projectc.mydomain.com:443>
    ServerName dev.projectc.mydomain.com
    WSGIScriptAlias / "C:/projectc/projectc.wsgi"
    CustomLog "logs/projectc_access.log" common
    ErrorLog "logs/projectc_error.log"
    SSLEngine on
    SSLCertificateFile "C:/path/to/projectc_cert/cert.cer"
    SSLCertificateKeyFile "C:/path/to/projectc_cert/project.key"
    <Directory C:\projectc>
        Require all granted
    </Directory>
</VirtualHost>

问题表现

  • 访问ProjectA正常,但访问ProjectB出现500错误,日志报错:
[Wed May 10 09:13:49.594211 2023] [wsgi:error] [pid 17300:tid 1400] [client 9.26.10.10:15429] ModuleNotFoundError: No module named 'appa2'\r, referer: https://dev.projectb.mydomain.com/
  • ProjectB中并无appa2模块;重启Apache后先访问ProjectB则正常,但访问其他项目(如ProjectA)会报错找不到appb1模块。

各项目WSGI文件配置

import os
import platform
import sys
from pathlib import Path

# Activate the project specific virtual environment
path = Path(__file__).resolve().parent.parent
# Set the path to the project root in the system PATH
sys.path.insert(0, str(path))
activate_dir = "Scripts" if platform.system() == "Windows" else "bin"
activate_script = "activate_this.py"
activate_path = path / "venv" / activate_dir / activate_script
if activate_path.is_file():
    exec(
        compile(open(activate_path).read(), activate_path, "exec"),
        dict(__file__=activate_path),
    )

# Import django-environ which is installed in the venv
import environ

ROOT_DIR = Path(__file__).parent.parent
# `projecta` is changed to `projectb` and `projectc` in each project appropriately
env = environ.Env(
    DJANGO_SETTINGS_MODULE=(str, "projecta.settings.base"),
)
env.read_env(ROOT_DIR / ".env")

# Load up the django application
settings_module = env.str("DJANGO_SETTINGS_MODULE")
if not settings_module:
    # `projecta` is changed to `projectb` and `projectc` in each project appropriately
    os.environ["DJANGO_SETTINGS_MODULE"] = "projecta.settings.base"

from django.core.wsgi import get_wsgi_application

application = get_wsgi_application()

已确认各项目.env文件配置正确,需排查并解决该问题。


排查与解决方法

核心原因

mod_wsgi默认以嵌入式模式运行,所有VirtualHost的WSGI应用共享同一个Apache进程。第一个项目加载后,其模块路径和已加载的模块会被后续项目继承,导致模块查找逻辑混乱(比如ProjectA加载的appa2会被ProjectB的Python解释器误查找)。

解决步骤

1. 启用守护进程模式,实现项目进程隔离

在每个项目的443 VirtualHost配置块中添加守护进程配置,让每个项目运行在独立的进程组:

以ProjectA为例修改配置:

<VirtualHost dev.projecta.mydomain.com:443>
    ServerName dev.projecta.mydomain.com
    # 新增守护进程配置
    WSGIDaemonProcess projecta python-home=C:/projecta/venv python-path=C:/projecta
    WSGIProcessGroup projecta
    
    WSGIScriptAlias / "C:/projecta/projecta.wsgi"
    CustomLog "logs/projecta_access.log" common
    ErrorLog "logs/projecta_error.log"
    SSLEngine on
    SSLCertificateFile "C:/path/to/projecta_cert/cert.cer"
    SSLCertificateKeyFile "C:/path/to/projecta_cert/project.key"
    <Directory C:\projecta>
        Require all granted
    </Directory>
</VirtualHost>

同理修改ProjectB和ProjectC的配置,将projecta替换为projectb/projectc,并确保python-home指向对应项目的虚拟环境根目录,python-path指向项目根目录。

2. 优化WSGI文件,避免路径污染

当前WSGI文件的sys.path.insert(0, str(path))会把项目路径插入全局路径最前面,在共享进程下会干扰后续项目。修改WSGI文件,重置路径并仅添加当前项目路径:

import os
import sys
from pathlib import Path

# 重置sys.path,保留系统默认路径,避免继承其他项目的路径
sys.path = sys.path[:]

# 添加当前项目根路径到sys.path
path = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(path))

import environ

ROOT_DIR = Path(__file__).parent.parent
# 替换为对应项目的默认设置
env = environ.Env(
    DJANGO_SETTINGS_MODULE=(str, "projecta.settings.base"),
)
env.read_env(ROOT_DIR / ".env")

settings_module = env.str("DJANGO_SETTINGS_MODULE")
if not settings_module:
    # 替换为对应项目的设置路径
    os.environ["DJANGO_SETTINGS_MODULE"] = "projecta.settings.base"

from django.core.wsgi import get_wsgi_application

application = get_wsgi_application()

可以去掉原WSGI文件中的虚拟环境激活逻辑,因为WSGIDaemonProcess的python-home已经指定了虚拟环境,mod_wsgi会自动使用该环境的Python解释器。

3. 重启Apache并验证

修改配置后重启Apache服务,依次访问所有项目,确认模块找不到的错误是否消失。

额外检查点

  • 确认每个项目的INSTALLED_APPS配置正确,未引用其他项目的应用。
  • 检查Apache进程对各项目目录的访问权限,确保文件可读取。
  • 验证各项目的虚拟环境独立,依赖无交叉安装。

内容的提问来源于stack exchange,提问作者UpDawg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 14:02:58