最终,您的问题似乎实际上是关于如何检测正在运行的 Python 是否在 virtualenv 中。要深入了解这一点,我们必须了解virtualenv
实际工作原理。
当您activate
在 virtualenv 中运行脚本时,它会做两件事:
- 它更新
PATH
环境变量以包含bin
来自 virtualenv 的目录,这样当你python
从 virtualenv 运行二进制文件时,它就会运行。
- 它设置一个变量
VIRTUAL_ENV
,以便激活脚本本身可以跟踪激活。
直接python
从 virtualenv 运行是完全可以接受的,并且在运行时python
根本不使用该VIRTUAL_ENV
变量。相反,它确定包含正在运行的python
二进制文件的目录并使用父目录作为其“前缀”。
sys
您可以通过导入模块和咨询来确定系统的前缀sys.prefix
。但是,在未激活virtualenv 时依赖 this 的值是一个坏主意,因为这是 Python 的构建时设置,可以轻松自定义,并且肯定会因平台而异。
然而,当 Python从 virtualenv 前缀与其编译的前缀运行时,它确实有一点运行时差异:包sys
有一个额外的变量real_prefix
,它返回编译到 Python 二进制文件中的前缀。因此,可以使用它来识别 Python 正在非默认位置运行,这很可能意味着它是从 virtualenv 运行的:
import sys
if getattr(sys, "real_prefix", None) is not None:
print "Maybe in a virtualenv"
else:
print "Probably not in a virtualenv"
然而,即使这也不是一门精确的科学。这一切真正告诉你的是,python 二进制文件不在编译时指定的位置。它不会告诉您当前用户是否有权写入/usr/share/man
- 在某些(可能是边缘)情况下,这不会给您正确的答案:
如果用户已经从他的主目录中的源代码编译了他自己的 Python 并且它的编译前缀/home/johnd/local-python
将real_prefix
不会被设置,但用户仍然可以写访问他的 Pythonlib
目录,并且可能没有写访问/etc
或/usr/share/man
同样,在某些系统上,管理员可能已授予/usr/lib/python2.7
特定应用程序开发人员组的组写入权限,以便他们可以安装 Python 模块,但未授予他们对其他系统文件的写入权限。
所以我认为最终你能做的最好的就是启发式方法,最好避免在data_files
你希望在 virtualenv 中使用的任何模块中使用绝对路径。折衷方案可能是将您的模块简单地拆分为两个发行版,一个代表可本地化的源文件,另一个代表系统范围的配置以使其运行。后者可以依赖前者,这样用户仍然可以轻松安装它,但使用者可以virtualenv
选择直接使用另一个前者。