Changing PYTHONHOME causes ImportError: No module named site
Changing PYTHONHOME causes ImportError: No module named site
我正在尝试通过 mod_wsgi 在 Apache 上部署 Flask 网络应用程序。我不能使用默认的 Python 环境,因为它是用 UCS-2 Unicode 而不是 UCS-4 编译的,我不能为这种情况重新编译它。因此,虚拟环境。无论如何都会使用虚拟环境,但该错误意味着我无法使用默认的 Python 安装并仅将虚拟环境的模块添加到 PYTHONPATH
,否则会让我完全偶然地避免了当前的问题。
我找到了 documentation for mod_wsgi
to change which Python executable to use。但是,当尝试这样做时,服务器无法正常工作。 /var/log/httpd/error_log
迅速充斥着行 ImportError: No module named site
。
我已经检查了在这里和其他地方可以找到的所有类似问题,但还没有成功。实验表明,据我所知,在不激活虚拟环境的情况下更改 PYTHONHOME 时会出现问题 - 以及自动部署的工作方式(通过 Fabric),据我所知我无法激活虚拟环境。
Apache 配置
我目前的应用 httpd.conf
:
WSGIPythonPath /path/to/dir/containing/wsgi/file/and/app:/path/to/virtualenv/lib:/path/to/virtualenv/lib/site-packages
WSGIPythonHome /path/to/virtualenv
WSGISocketPrefix /var/run/wsgi
User user
Group group
<VirtualHost *>
ServerName servername.generic.com
DocumentRoot /path/to/dir/containing/wsgi/file/and/app/static_dev/
WSGIDaemonProcess appname user=user group=group threads=2
WSGIScriptAlias / /path/to/dir/containing/wsgi/file/and/app/app.wsgi
<Directory /path/to/dir/containing/wsgi/file/and/app>
WSGIProcessGroup appname
WSGIApplicationGroup %{GLOBAL}
Require all granted
</Directory>
</VirtualHost>
我从失败的尝试中找到的数据
我知道错误不在我的 app.wsgi
中,因为当我在最顶部添加行 raise Exception('tried to open the file')
来检查时,现有的 ImportError
一直在发生,而不是那个新 Exception
.
我已通过 ldd
确认我的 mod_wsgi
版本适用于 Python 2.7。
我试过设置WSGIPythonHome /path/to/virtualenv/bin/
和WSGIPythonHome /path/to/virtualenv/bin/python
,结果与当前状态相同。
我尝试省略 WSGIPythonHome
指令,在这种情况下,它会按原样加载 app.wsgi
,但会在稍后的导入时中断,如顶部所述(我不能这样做的原因就那样做)。
我曾尝试省略 WSGIPythonPath
指令并将其留给 app.wsgi
以将内容添加到 PYTHONPATH,结果与当前状态相同。
我尝试将路径设置作为 WSGIDaemonProcess
的参数而不是 WSGIPythonPath
指令,结果与当前状态相同。
我已经确认/path/to/virtualenv/lib
中有一个site.py
。
我已经确认没有其他正在使用的非特定于应用程序的 Apache .conf
文件(默认设置、自动模块加载等)包含字符串 "WSGI",所以我不认为这里有任何冲突。
如果我从命令行激活虚拟环境,我可以导入 site
而不会出错,只是为了测试它确实存在于环境中。但是,这还不够,因为使用的部署工具需要从对 sudo systemctl start httpd.service
的单个调用顺利启动,而这似乎并不关心当前 shell 会话的 venv。
如果在默认状态下,我 export PYTHONHOME=/path/to/virtualenv
,尝试打开 Python REPL 会立即退出并显示 ImportError: No module named site
。
如果我激活虚拟环境然后设置 PYTHONHOME
,我会得到同样的导入错误。
如果我激活虚拟环境并且不触摸 PYTHONHOME
,echo $PYTHONHOME
输出一个空行,Python REPL 工作正常。在 virtualenv 中的 Python REPL 中:
(virtualenv)-bash-4.2$ python
Python 2.7.8 (default, Aug 14 2014, 13:26:38)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.prefix
'/path/to/virtualenv'
>>> sys.exec_prefix
'/path/to/virtualenv'
即使将 PYTHONHOME
设置为相同的值也不起作用。
如果我尝试 export PYTHONHOME=:/path/to/virtualenv
或 export PYTHONHOME=/path/to/virtualenv:
,明确仅设置 prefix
和 exec_prefix
之一,在任何一种情况下都会失败并出现相同的导入错误。
如果我激活虚拟环境并以后两种方式之一设置 PYTHONHOME
,未设置的似乎默认为 /
而不是通常的默认值,但是 Python REPL 运行很好:
# Setting only exec_prefix
(virtualenv)-bash-4.2$ export PYTHONHOME=:/path/to/virtualenv
(virtualenv)-bash-4.2$ python
Python 2.7.8 (default, Aug 14 2014, 13:26:38)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.prefix
'/'
>>> sys.exec_prefix
'/path/to/virtualenv'
>>> quit()
# Setting only prefix
(.virtualenv)-bash-4.2$ export PYTHONHOME=/path/to/virtualenv:
(.virtualenv)-bash-4.2$ python
Python 2.7.8 (default, Aug 14 2014, 13:26:38)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.prefix
'/path/to/virtualenv'
>>> sys.exec_prefix
'/'
不幸的是,由于部署脚本不关心激活什么环境,所以这并不能解决问题。尝试以这种方式设置 WSGIPythonHome
没有任何区别。
我还注意到一件事:virtualenv 中的 Python 是 2.7.8。 virtualenv (usr/bin/python
) 之外的 Python 运行 是 2.7.5。我不知道 - 这会以某种方式影响 PYTHONHOME
的设置吗?我希望不会 - 因为与仅在 app.wsgi
文件中设置 sys.path
相比,这似乎破坏了使用 WSGIPythonHome
到 运行 virtualenv 的全部目的,能够从不同的可执行文件开始 - 但我不能排除这种可能性,因为我一无所知。
/path/to/virtualenv/bin/python
中的 2.7.8 Python 的 sys.real_prefix
为 /network-mounted-drive/sw/python/python-2.7.8
。
我将部署更改为从 /network-mounted-drive/sw/python/python-2.7.5
构建,然后进行了更多测试。结果如下:
尝试启动 httpd 会出现与之前相同的导入错误。
设置PYTHONHOME为虚拟环境的位置,然后运行ning python:
-bash-4.2$ echo $PYTHONHOME
/path/to/virtualenv
-bash-4.2$ python
ImportError: No module named site
将 PYTHONHOME 设置为虚拟环境的位置,然后显式 运行ning 虚拟环境的 python 二进制文件(激活虚拟环境然后 运行ning python
给出相同的结果):
# In the directory just above the virtualenv
-bash-4.2$ ./virtualenv/bin/python
Python 2.7.5 (default, Mar 14 2016, 14:13:09)
[GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.prefix
'/path/to/virtualenv'
>>> sys.exec_prefix
'/path/to/virtualenv'
>>> sys.real_prefix
'/network-mounted-drive/sw/python/python-2.7.5
有人知道吗?
已找到解决方案:问题似乎出在尝试使用从系统上本地 python 安装以外的东西构建的虚拟环境。
通过将 "local python install on the deployment VM doesn't have pip installed" 的问题向上推给具有安装 pip 所需权限的人来解决,因为没有尝试通过网络 python 安装的解决方法奏效。
实际使用从网络驱动器上的 Python 安装链接的虚拟环境的问题 mod_wsgi 可能无法解决,或者至少我无法在合理的数量上解决它相对于官僚解决方案的时间。
我正在尝试通过 mod_wsgi 在 Apache 上部署 Flask 网络应用程序。我不能使用默认的 Python 环境,因为它是用 UCS-2 Unicode 而不是 UCS-4 编译的,我不能为这种情况重新编译它。因此,虚拟环境。无论如何都会使用虚拟环境,但该错误意味着我无法使用默认的 Python 安装并仅将虚拟环境的模块添加到 PYTHONPATH
,否则会让我完全偶然地避免了当前的问题。
我找到了 documentation for mod_wsgi
to change which Python executable to use。但是,当尝试这样做时,服务器无法正常工作。 /var/log/httpd/error_log
迅速充斥着行 ImportError: No module named site
。
我已经检查了在这里和其他地方可以找到的所有类似问题,但还没有成功。实验表明,据我所知,在不激活虚拟环境的情况下更改 PYTHONHOME 时会出现问题 - 以及自动部署的工作方式(通过 Fabric),据我所知我无法激活虚拟环境。
Apache 配置
我目前的应用 httpd.conf
:
WSGIPythonPath /path/to/dir/containing/wsgi/file/and/app:/path/to/virtualenv/lib:/path/to/virtualenv/lib/site-packages
WSGIPythonHome /path/to/virtualenv
WSGISocketPrefix /var/run/wsgi
User user
Group group
<VirtualHost *>
ServerName servername.generic.com
DocumentRoot /path/to/dir/containing/wsgi/file/and/app/static_dev/
WSGIDaemonProcess appname user=user group=group threads=2
WSGIScriptAlias / /path/to/dir/containing/wsgi/file/and/app/app.wsgi
<Directory /path/to/dir/containing/wsgi/file/and/app>
WSGIProcessGroup appname
WSGIApplicationGroup %{GLOBAL}
Require all granted
</Directory>
</VirtualHost>
我从失败的尝试中找到的数据
我知道错误不在我的 app.wsgi
中,因为当我在最顶部添加行 raise Exception('tried to open the file')
来检查时,现有的 ImportError
一直在发生,而不是那个新 Exception
.
我已通过 ldd
确认我的 mod_wsgi
版本适用于 Python 2.7。
我试过设置WSGIPythonHome /path/to/virtualenv/bin/
和WSGIPythonHome /path/to/virtualenv/bin/python
,结果与当前状态相同。
我尝试省略 WSGIPythonHome
指令,在这种情况下,它会按原样加载 app.wsgi
,但会在稍后的导入时中断,如顶部所述(我不能这样做的原因就那样做)。
我曾尝试省略 WSGIPythonPath
指令并将其留给 app.wsgi
以将内容添加到 PYTHONPATH,结果与当前状态相同。
我尝试将路径设置作为 WSGIDaemonProcess
的参数而不是 WSGIPythonPath
指令,结果与当前状态相同。
我已经确认/path/to/virtualenv/lib
中有一个site.py
。
我已经确认没有其他正在使用的非特定于应用程序的 Apache .conf
文件(默认设置、自动模块加载等)包含字符串 "WSGI",所以我不认为这里有任何冲突。
如果我从命令行激活虚拟环境,我可以导入 site
而不会出错,只是为了测试它确实存在于环境中。但是,这还不够,因为使用的部署工具需要从对 sudo systemctl start httpd.service
的单个调用顺利启动,而这似乎并不关心当前 shell 会话的 venv。
如果在默认状态下,我 export PYTHONHOME=/path/to/virtualenv
,尝试打开 Python REPL 会立即退出并显示 ImportError: No module named site
。
如果我激活虚拟环境然后设置 PYTHONHOME
,我会得到同样的导入错误。
如果我激活虚拟环境并且不触摸 PYTHONHOME
,echo $PYTHONHOME
输出一个空行,Python REPL 工作正常。在 virtualenv 中的 Python REPL 中:
(virtualenv)-bash-4.2$ python
Python 2.7.8 (default, Aug 14 2014, 13:26:38)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.prefix
'/path/to/virtualenv'
>>> sys.exec_prefix
'/path/to/virtualenv'
即使将 PYTHONHOME
设置为相同的值也不起作用。
如果我尝试 export PYTHONHOME=:/path/to/virtualenv
或 export PYTHONHOME=/path/to/virtualenv:
,明确仅设置 prefix
和 exec_prefix
之一,在任何一种情况下都会失败并出现相同的导入错误。
如果我激活虚拟环境并以后两种方式之一设置 PYTHONHOME
,未设置的似乎默认为 /
而不是通常的默认值,但是 Python REPL 运行很好:
# Setting only exec_prefix
(virtualenv)-bash-4.2$ export PYTHONHOME=:/path/to/virtualenv
(virtualenv)-bash-4.2$ python
Python 2.7.8 (default, Aug 14 2014, 13:26:38)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.prefix
'/'
>>> sys.exec_prefix
'/path/to/virtualenv'
>>> quit()
# Setting only prefix
(.virtualenv)-bash-4.2$ export PYTHONHOME=/path/to/virtualenv:
(.virtualenv)-bash-4.2$ python
Python 2.7.8 (default, Aug 14 2014, 13:26:38)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.prefix
'/path/to/virtualenv'
>>> sys.exec_prefix
'/'
不幸的是,由于部署脚本不关心激活什么环境,所以这并不能解决问题。尝试以这种方式设置 WSGIPythonHome
没有任何区别。
我还注意到一件事:virtualenv 中的 Python 是 2.7.8。 virtualenv (usr/bin/python
) 之外的 Python 运行 是 2.7.5。我不知道 - 这会以某种方式影响 PYTHONHOME
的设置吗?我希望不会 - 因为与仅在 app.wsgi
文件中设置 sys.path
相比,这似乎破坏了使用 WSGIPythonHome
到 运行 virtualenv 的全部目的,能够从不同的可执行文件开始 - 但我不能排除这种可能性,因为我一无所知。
/path/to/virtualenv/bin/python
中的 2.7.8 Python 的 sys.real_prefix
为 /network-mounted-drive/sw/python/python-2.7.8
。
我将部署更改为从 /network-mounted-drive/sw/python/python-2.7.5
构建,然后进行了更多测试。结果如下:
尝试启动 httpd 会出现与之前相同的导入错误。
设置PYTHONHOME为虚拟环境的位置,然后运行ning python:
-bash-4.2$ echo $PYTHONHOME
/path/to/virtualenv
-bash-4.2$ python
ImportError: No module named site
将 PYTHONHOME 设置为虚拟环境的位置,然后显式 运行ning 虚拟环境的 python 二进制文件(激活虚拟环境然后 运行ning python
给出相同的结果):
# In the directory just above the virtualenv
-bash-4.2$ ./virtualenv/bin/python
Python 2.7.5 (default, Mar 14 2016, 14:13:09)
[GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.prefix
'/path/to/virtualenv'
>>> sys.exec_prefix
'/path/to/virtualenv'
>>> sys.real_prefix
'/network-mounted-drive/sw/python/python-2.7.5
有人知道吗?
已找到解决方案:问题似乎出在尝试使用从系统上本地 python 安装以外的东西构建的虚拟环境。
通过将 "local python install on the deployment VM doesn't have pip installed" 的问题向上推给具有安装 pip 所需权限的人来解决,因为没有尝试通过网络 python 安装的解决方法奏效。
实际使用从网络驱动器上的 Python 安装链接的虚拟环境的问题 mod_wsgi 可能无法解决,或者至少我无法在合理的数量上解决它相对于官僚解决方案的时间。