Python 排序sys.path:首先是virtualenv,然后是/usr

Python 排序sys.path:首先是virtualenv,然后是/usr,python,path,pip,virtualenv,Python,Path,Pip,Virtualenv,为什么sys.path在my virtualenv的目录之前包含/usr/… 我使用--系统站点包创建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/python

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

我使用
--系统站点包创建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
/home/my virtualenv/src/foo

/usr/lib/python2.7/site-packages您可以在模块导入之前简单地预先设置所需的路径。有点黑,但应该能解决你的问题

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

import lalala

下面是解决问题的简单方法:

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

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

在@Jan Philip Gehrcke建议的代码行下方:

sys.path = sorted(sys.path, key=lambda x: x.startswith(prefix), reverse=True)
3-运行您的程序并享受

此解决方案可帮助您对
sys.path
列表进行排序,而无需在程序主体中添加烦人的行


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

如果使用交互式shell,则可以设置
PYTHONSTARTUP
,或者还可以设置一些bash别名,以您喜欢的方式修改
PYTHONPATH
。 您还可以在
virtualenv
bin
目录中修改激活文件
activate.csh
activate\u this.py
;或
site.py
文件作为另一个响应


pip+virtualenv
is-正如已经指出的那样,对于系统范围的软件包来说,它不是一个非常友好的组合,也就是说,在构建环境时,使用系统numpy或软件包x,y没有默认标志。尽管正如评论中所建议的那样,我也建议使用
--无站点包构建,然后在讨论后从
/usr/lib
编辑中专门导入所需内容:

sys.path = sorted(sys.path, key=lambda x: x.startswith(prefix), reverse=True)
“我希望我的virtualenv(/usr…)之外的所有路径都位于 virtualenv的路径。[…]需要对其进行排序。“

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

sys.path = sorted(sys.path, key=lambda x: x.startswith(prefix), reverse=True)
sorted()
的排序行为是稳定的:对于具有相同排序键的项目,保留原始顺序。这里只使用两个排序键:
True
False
。你需要想出一个可靠的方法来设置你的
前缀(你可能想硬编码它,或者根据当前的工作目录来确定它,我相信你会找到一种方法)

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

sys.path = sorted(sys.path, key=lambda x: x.startswith(prefix), reverse=True)
您不想过多地阐述您的需求和应用程序场景,因此我提供了一个更一般的答案:您可能需要过度思考您的方法,并且可能不希望
virtualenv
完全解决您的问题

在某些情况下,
virtualenv
并不是完美的解决方案。这是一个折衷方案,本文详细描述了折衷方案的一个方面:

在许多场景中,
virtualenv
发挥了出色的作用,工作做得非常出色!当然,这对我帮助很大,尤其是在发展方面。在其他场景中,它不是一个完整的解决方案,甚至是一个糟糕的解决方案

因此,现在我看到了几个不同的选择:

  • 使用virtualenv,但是控制那些你需要改变的事情。例如,在执行特定导入之前,从包中修改
    sys.path
    。虽然有些人可能认为这是“不干净的”,但它确实是一种快速有效地控制目录搜索顺序的方法。code>sys.path.insert(1,foo)
  • 实际上被许多包和测试环境使用。这并不罕见。这种方法可以在工作一分钟后为您提供有效的解决方案。试试看
  • 如果您认为您的案例中的virtualenv的行为没有记录在案,或者没有清楚地显示错误行为,那么请向项目报告您的发现。他们一定会感激你的简明反馈
  • 如果您认为virtualenv没有提供应用程序案例中所需的隔离或控制级别,那么您可能希望查看其他选项,例如Docker或Vagrant,或者完全支持虚拟机

  • 我发现解决此问题的一个简单方法是将您的virtualenv site packages文件夹添加到$VIRTUAL_ENV/lib/python2.7/site-packages//virtualenv\u path\u extensions.pth文件中,或者在激活环境后进入shell:

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

    这将强制将文件夹显示在系统文件夹之前,正如我注意到添加的其他路径一样

    我相信这不是最干净的解决方案,但确实virtualenv奇怪地排列了路径


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

    “我不能在我的上下文中使用
    ——没有站点包”
    :请详细说明。@Kevin我可以解释,但会有什么变化?我不能使用——在我的上下文中没有站点包——就是这样。问题是如何对sys.path进行排序:-)坦率地说,
    --系统站点包
    已损坏。在virtualenv中安装所有内容几乎总是更好的。您的情况(显然)不同,这使得我很难在没有更多信息的情况下给您一个有用的答案。这种限制(无
    --无站点包
    )是因为一些共享的全局包吗?如果是这样,为什么不在virtualenv中复制它们呢?我更新了这个问题,并在cetain中添加了“为什么我使用系统站点包”一节