对sys.path进行排序:首先是virtualenv,然后是/ usr

时间:2015-01-30 15:43:12

标签: python path pip virtualenv

为什么sys.path在我的virtualenv目录之前包含/usr/...

我用--system-site-packages

创建了virtualenv

目前sys.path看起来像这样:

/home/my-virtualenv/src/foo
/usr/lib/python2.7/site-packages        <--- /usr paths should be below 
/usr/lib64/python2.7/site-packages
/home/my-virtualenv/lib/python27.zip
/home/my-virtualenv/lib64/python2.7
/home/my-virtualenv/lib64/python2.7/plat-linux2
/home/my-virtualenv/lib64/python2.7/lib-tk
/home/my-virtualenv/lib64/python2.7/lib-old
/home/my-virtualenv/lib64/python2.7/lib-dynload
/usr/lib64/python2.7
/usr/lib/python2.7
/usr/lib64/python2.7/lib-tk
/home/my-virtualenv/lib/python2.7/site-packages

我希望我的virtualenv(/usr...)之外的所有路径都低于virtualenv的路径。

否则会发生疯狂的事情:我用pip安装一个软件包。 Pip告诉我安装了新版本(pip freeze | grep -i ...),但导入确实使用了/usr/lib/python2.7/site-packages

中的版本

我不能在我的上下文中使用--no-site-packages

有没有办法对sys.path进行排序?

为什么我使用system-site-packages

似乎没有直接的方法可以从virtualenv中提供的全局站点包中创建单个库。看到这个问题: make some modules from global site-packages available in virtualenv

像python-gtk这样的软件包很难在virtualenv中安装。

5 个答案:

答案 0 :(得分:2)

您可以在模块导入之前简单地添加所需的路径。有点hacky,但应该解决你的问题

import sys
sys.path.insert(1, '/home/my-virtualenv/lib/python2.7/site-packages')

import lalala

答案 1 :(得分:2)

在讨论后编辑:

  

&#34;我希望我的virtualenv(/ usr ...)之外的所有路径都低于   virtualenv的路径。 [...]需要对其进行排序。&#34;

然后,只需在第一次导入之前对sys.path进行排序。给定与您的virtalenv位置相对应的特定路径prefix,这种方法可能就足够了:

sys.path = sorted(sys.path, key=lambda x: x.startswith(prefix), reverse=True)

sorted()的排序行为是稳定的:对具有相同排序键的项目保留原始顺序。此处仅使用了两个排序键:TrueFalse。您需要提出一种可靠的方法来设置prefix(您可能希望对其进行硬编码,或者根据当前工作目录确定它,我相信您找到了办法)。

原始答案(通常仍然有效):

您不想过多地详细说明您的要求和应用场景,因此我提供了一个更一般的答案:您可能需要过度思考您的方法,并且可能不希望virtualenv完全解决您的问题。< / p>

在某些情况下,virtualenv不是完美的解决方案。它的折衷方案,本文详尽描述了这种妥协的一方:https://pythonrants.wordpress.com/2013/12/06/why-i-hate-virtualenv-and-pip/

在许多情况下,virtualenv有着出色的目的,并且工作得非常好!它确实给了我很多帮助,特别是对于开发目的。在其他情况下,它要么不是一个完整的解决方案,要么是一个糟糕的解决方案。

所以,我现在有几个不同的选择:

  1. 使用virtualenv,但要控制您需要更改的内容。例如,在执行某项导入之前,在您的包中修改sys.path。虽然有些人可能会考虑这个&#34;不干净&#34;,但它确实是一种快速有效地控制目录搜索顺序的方法。 许多包和测试环境实际上使用sys.path.insert(1, foo)。这根本不常见。这种方法可以在一分钟的工作后为您提供工作解决方案。试一试!
  2. 如果您认为您案例中的virtualenv表现不符合记录或明确显示错误行为,请将结果报告给项目。他们一定会很感激您的简明反馈。
  3. 如果您认为virtualenv不提供应用程序案例中所需的隔离级别或控制级别,您可能需要查看其他选项,例如Docker或Vagrant或全功能虚拟机。

答案 2 :(得分:1)

如果您使用的是互动式外壳,则可以设置PYTHONSTARTUP,或者设置一些bash别名,以您喜欢的方式修改PYTHONPATH。 您还可以修改activate.csh的{​​{1}}目录中的激活文件activate_this.pybin;或virtualenv文件作为另一个提到的回复。

site.py - 因为已经指出系统级软件包不是一个非常友好的组合,即没有默认标志用于说使用system numpy 包x,y 在构建环境时。虽然正如评论中所建议的那样,我也建议使用pip + virtualenv构建,然后从--no-site-packages

专门导入您需要的内容

答案 3 :(得分:0)

以下解决方案解决您的问题:

1-打开my-virtualenv/lib/python2.7/site.py文件进行编辑。

2-在此文件末尾附加排序算法(或解决问题的任何代码)的下方行(没有第一行缩进):

prefix = __file__.rsplit(os.sep, 3)[0]

以下代码行建议@ Jan-Philip Gehrcke:

sys.path = sorted(sys.path, key=lambda x: x.startswith(prefix), reverse=True)

3-运行程序并享受

此解决方案可帮助您对sys.path列表进行排序,而不会在程序正文中添加恼人的行。

注意:初始化期间会自动导入site模块。可以使用解释器的-S选项来禁止自动导入。

答案 4 :(得分:0)

我发现解决此问题的一种简单方法就是将virtualenv site-packages文件夹添加到$ VIRTUAL_ENV / lib / python2.7 / site-packages / _virtualenv_path_extensions.pth文件中,或者在激活环境后输入shell :

$ add2virtualenv $VIRTUAL_ENV/lib/python2.7/site-packages

这会强制显示系统文件夹之前的文件夹,因为我注意到它添加了其他路径。

我相信这不是最干净的解决方案,但事实上,virtualenv奇怪地命令道路。

另一个观察是当我启动ipython时,sys.path以合理的顺序出现,但是当在python解释器内部没有时,不知道为什么。