【问题标题】:Apache + mod_wsgi - Python doesn't load installed modulesApache + mod_wsgi - Python 不加载已安装的模块
【发布时间】:2026-02-10 07:10:02
【问题描述】:

我有一个带有 mod_wsgi 的 Apache 服务器,运行 Python 2.7 脚本。 该脚本使用通过 pip 安装的 python Pillow 模块。

使用python script.py 正常运行脚本可以正常运行,但从 wsgi 运行脚本时 - 会为 PIL 引发 ImportError 异常。

这是来自/etc/apache2/sites-enabled/000-default.conf的Apache配置:

<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        WSGIScriptAlias /wsgi/ /home/nitay/Desktop/WebsitePath/Python/wsgi.py

        <Directory "/home/nitay/Desktop/WebsitePath/Python">
            Require all granted
        </Directory>
</VirtualHost>

没有安装 virtualenv,这台机器上只安装了一个 Python。

我该怎么做才能让 python 找到它安装的模块?

我已经看到使用 mod_wsgi 的 daemon mode 手动定义 python 路径的解决方案。有没有办法在嵌入式模式下这样做?

编辑: Apache 错误日志:

[Wed Nov 02 16:08:02.931400 2016] [wsgi:error] [pid 48202:tid 140100207392512] [client 192.168.1.179:29223] mod_wsgi (pid=48202): Target WSGI script '/home/nitay/Desktop/WebsitePath/Python/wsgi.py' cannot be loaded as Python module., referer: http://192.168.1.247/index.html
[Wed Nov 02 16:08:02.931475 2016] [wsgi:error] [pid 48202:tid 140100207392512] [client 192.168.1.179:29223] mod_wsgi (pid=48202): Exception occurred processing WSGI script '/home/nitay/Desktop/WebsitePath/Python/wsgi.py'., referer: http://192.168.1.247/index.html
[Wed Nov 02 16:08:02.931557 2016] [wsgi:error] [pid 48202:tid 140100207392512] [client 192.168.1.179:29223] Traceback (most recent call last):, referer: http://192.168.1.247/index.html
[Wed Nov 02 16:08:02.931601 2016] [wsgi:error] [pid 48202:tid 140100207392512] [client 192.168.1.179:29223]   File "/home/nitay/Desktop/WebsitePath/Python/wsgi.py", line 9, in <module>, referer: http://192.168.1.247/index.html
[Wed Nov 02 16:08:02.931687 2016] [wsgi:error] [pid 48202:tid 140100207392512] [client 192.168.1.179:29223]     import sprites, referer: http://192.168.1.247/index.html
[Wed Nov 02 16:08:02.931705 2016] [wsgi:error] [pid 48202:tid 140100207392512] [client 192.168.1.179:29223]   File "/home/nitay/Desktop/WebsitePath/Python/sprites.py", line 1, in <module>, referer: http://192.168.1.247/index.html
[Wed Nov 02 16:08:02.931767 2016] [wsgi:error] [pid 48202:tid 140100207392512] [client 192.168.1.179:29223]     from PIL import Image, referer: http://192.168.1.247/index.html
[Wed Nov 02 16:08:02.931830 2016] [wsgi:error] [pid 48202:tid 140100207392512] [client 192.168.1.179:29223] ImportError: No module named PIL, referer: http://192.168.1.247/index.html

普通 Python 和 WSGI 的 sys.path 和版本:

Normal:
>>> sys.version
'2.7.11+ (default, Apr 17 2016, 14:00:29) \n[GCC 5.3.1 20160413]'
>>> sys.path
['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/home/nitay/.local/lib/python2.7/site-packages', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/gtk-2.0']

WSGI:
>>> sys.version
2.7.11+ (default, Apr 17 2016, 14:00:29) [GCC 5.3.1 20160413] 
>>> sys.path
['/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib

【问题讨论】:

  • 当您正常运行并从 wsgi 运行时,我会匹配 sys.versionsys.path
  • 显示完整的错误消息和来自 Apache 错误日志的回溯。
  • 还要解释一下为什么要使用嵌入模式?无论如何,使用守护程序模式是首选设置。
  • 我想使用嵌入式模式,因为 mod_wsgi 可以工作,而设置 mod_wsgi 的过程并不顺利 - 很多事情都在途中中断。我想专注于这个项目的软件方面,但如果需要 - 守护进程模式它。为什么它是首选设置?
  • 看来 mod_wsgi 以 su 运行 python,当以 su 运行 python 时,路径不包含任何站点包文件夹。

标签: python apache python-2.7 pip mod-wsgi


【解决方案1】:

在我的例子中,模块安装在用户环境中,而不是机器的环境中。 我只是跑:

sudo -H pip3.7 install mako

-H 告诉sudo 将模块安装在机器根目录 vs 运行命令的用户目录中...

这是因为 Apache 无法访问/读取个人用户的文件。

【讨论】:

    【解决方案2】:

    我重新配置了服务器配置,这次正确命名,使用 virtualenv 和 wsgi 的守护程序模式。

    这是我最终得到的 apache 配置:

    <VirtualHost *:80>
            ServerAdmin webmaster@localhost
            DocumentRoot /var/www/
    
            ErrorLog ${APACHE_LOG_DIR}/error.log
            CustomLog ${APACHE_LOG_DIR}/access.log combined
    
            WSGIDaemonProcess sprites-toolbox python-path=/home/nitay/Desktop/SpritesToolbox/Python:/home/nitay/Desktop/SpritesToolbox/Python/sprite-toolbox-env/lib/python2.7/site-packages
            WSGIProcessGroup sprites-toolbox
    
            WSGIScriptAlias /wsgi/ /home/nitay/Desktop/SpritesToolbox/Python/wsgi.py
    
    
            <Directory "/home/nitay/Desktop/SpritesToolbox/Python">
                Require all granted
            </Directory>
    </VirtualHost>
    

    故事的寓意? “时间很宝贵,明智地浪费它”(不要半途而废的服务器配置)

    【讨论】:

    • 最佳做法是不要在python-path 中添加site-packages。使用python-home 选项指定虚拟环境的位置。见blog.dscpl.com.au/2014/09/…
    【解决方案3】:

    我对此感到困惑,上面的讨论确实很有帮助。然而,我的解决方案只是在我的 WSGI 程序的开头设置 Python 路径,例如:

    def application(environ, start_response):
        import sys
        path = "/usr/local/lib64/python2.7/site-packages/"
        if path not in sys.path: sys.path.append(path)
    

    【讨论】:

    • 您不应该在application() 通话中这样做。此外,添加该路径表明您的 mod_wsgi 很可能未针对您尝试使用的 Python 安装进行编译。永远不需要显式添加 Python 安装 site-packages 目录。如果混合安装 Python,我建议您可能会遇到其他问题。
    • 很难不同意您的观点,除非其他地方的其他人讨论过 Amazon Linux 和 WSGI 似乎存在问题。在许多版本的 Centos 中从未遇到过这个问题。我不知道在 Amazon Linux 上随 yum 安装的 wsgi 是否为它编译。这有效且不涉及对 Apache 配置的更改... YMMV。
    • 听起来他们可能会为您提供一个针对安装在/usr/local 下的 Python 2.7 编译的自定义 mod_wsgi,但仍然在/usr 下安装一个单独的系统 Python。如果是这种情况,他们应该在 Apache 配置中设置WSGIPythonHome /usr/local,否则它将使用/usr 下的 Python 安装文件,如果版本不完全相同,可能会导致一系列问题。
    • 我试过了,谢谢,但没用。谷歌显示这是一个已知问题。鉴于我所有的 WSGI 软件都在同一点开始并在完成后返回那里,这让我不必担心路径会以某种方式丢失。因为我在 Certbot 上也可能遇到类似的问题,所以我的解决方案将是恢复到 Centos,这是我的正常选择 - 有足够的工作要做,以免浪费时间解决操作系统问题。感谢您的帮助。