我有一个Python软件,其中包括配置文件和联机帮助页.要安装这些,我在我的内容中有以下行setup.py(如http://docs.python.org/2/distutils/setupscript.html#installing-additional-files中所述):
data_files = [('/etc/foo', ['foo.conf']), ('/usr/share/man/man1', ['foo.1'])]
Run Code Online (Sandbox Code Playgroud)
当我想以root身份安装软件时,这很好用python setup.py install,但当然在virtualenv中失败,因为不允许用户写入/etc和/usr/share/man.
解决这个问题的最佳做法是什么?检查VIRTUAL_ENV当前环境,根本不安装这些文件?该软件将foo.conf在本地目录中查找,因此应该没问题.用户会错过该联机帮助页,但无论如何都没有理智的安装方式,因为man在virtualenv附近的任何地方都不会找到它.
Mar*_*ins 10
最终,你的问题似乎是关于如何检测正在运行的Python是否属于virtualenv.要深究这一点,我们必须了解其virtualenv实际效果.
当您activate在virtualenv中运行脚本时,它会做两件事:
PATH环境变量以包含binvirtualenv中的目录,这样当你python从virtualenv运行二进制文件时就会运行.VIRTUAL_ENV以便激活脚本本身可以跟踪激活.python从virtualenv 直接运行它是完全可以接受的,并且在运行时python根本不使用该VIRTUAL_ENV变量.相反,它确定包含正在运行的python二进制文件的目录,并使用父目录作为其"前缀".
您可以通过导入sys模块和咨询来确定系统的前缀sys.prefix.但是,当virtualenv 未被激活时依赖于它的值是一个坏主意,因为这是Python的构建时设置,可以轻松定制,并且它肯定会在不同平台之间变化.
但是,当从virtualenv前缀与其编译前缀运行时,Python确实有一个轻微的运行时差异:该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"
Run Code Online (Sandbox Code Playgroud)
然而,即使这不是一门精确的科学.所有这些都告诉你,python二进制文件不在编译时指定的位置.它不会告诉您当前用户是否有权写入/usr/share/man- 有一些(可能是边缘)情况,这将无法给出正确的答案:
如果用户在他的主目录中从源编译了自己的Python,/home/johnd/local-python那么它的编译前缀real_prefix将不会被设置,但是用户仍然具有对他的Python lib目录的写访问权,并且可能没有写入权限/etc或者/usr/share/man
同样,在某些系统上,管理员可能已授予/usr/lib/python2.7某组应用程序开发人员组写权限,以便他们可以安装Python模块,但不授予他们对其他系统文件的写访问权限.
所以我认为最终你可以做的最好的是启发式,而且最好避免在data_files你想要在virtualenv中使用的任何模块中使用绝对路径.折衷方案可能是简单地将模块拆分为两个分布,一个代表可本地化的源文件,另一个代表系统范围的配置以使其运行.后者可以依赖于前者,以便用户仍然可以轻松地安装它,但那些使用virtualenv可以选择直接使用其他前者.