2011-05-12 105 views
15

如果我安装了从easy_install安装的软件包,则在PYTHONPATH变量中的项之前的蛋预先添加到sys.pathPYTHONPATH环境变量前的路径中的鸡蛋

举例来说,如果我有一个鸡蛋包叫做安装,以及一个名为FOO在当前目录包,然后做到这一点:

PYTHONPATH="." python 
>>> import foo 

这将使用蛋版本的foo而不是本地目录。检查sys.path显示鸡蛋放置在之前项目从PYTHONPATH。这似乎打破了。有什么方法可以覆盖这种行为吗?

+0

你确定它不会拿起或可能不理想从当前目录打包?通常,'sys.path'中的第一个条目应该总是空字符串,即它会先查看当前目录。 – kynan 2013-01-12 18:27:30

+0

不可以,因为蛋加载程序*预先放置它的路径,所以它在当前目录之前结束。 – jterrace 2013-01-12 21:19:02

+0

在其他*站点*包之前,但在交互式运行时,'sys.path'中的第一项始终是'''',请参见[文档](http://docs.python.org/2/library /sys.html?highlight=sys.path#sys.path)。无论“PYTHONPATH”如何,都是这种情况。 – kynan 2013-01-12 23:40:08

回答

11

不幸的是,这是通过setuptools/command/easy_install.py内部的硬编码模板完成的。您可以使用已编辑的模板创建一个修补过的setuptools,但我发现没有干净的方式来从外部扩展easy_install。

每次运行easy_install时,都会重新生成文件easy_install.pth。这是一个快速脚本,您可以在easy_install之后运行,以从easy_install.pth中删除页眉和页脚。你可以创建一个包装外壳脚本easy_install后立即运行此:

#!/usr/bin/env python 
import sys 
path = sys.argv[1] 
lines = open(path, 'rb').readlines() 
if lines and 'import sys' in lines[0]: 
    open(path, 'wb').write(''.join(lines[1:-1]) + '\n') 

例子:

% easy_install gdata 
% PYTHONPATH=xyz python -c 'import sys; print sys.path[:2]' 
['', '/Users/pat/virt/lib/python2.6/site-packages/gdata-2.0.14-py2.6.egg'] 

% ./fix_path ~/virt/lib/python2.6/site-packages/easy_install.pth 
% PYTHONPATH=xyz python -c 'import sys; print sys.path[:2]' 
['', '/Users/pat/xyz'] 

更多的澄清,这里是easy-install.pth格式:

import sys; sys.__plen = len(sys.path) 
./gdata-2.0.14-py2.6.egg 
import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,'__egginsert',0); sys.path[p:p]=new; sys.__egginsert = p+len(new) 

两个import sys线是导致鸡蛋出现在路径开始处的罪魁祸首。我的脚本只是删除那些sys.path -munging线。

+0

我很困惑 - 这不就是把鸡蛋完全从路上移走吗? – jterrace 2011-05-13 17:46:45

+0

我更新了我的答案,以显示easy-install.pth的内容。 – samplebias 2011-05-13 17:49:52

+5

当路径/蛋添加到'sys.path'时,用户站点没有优先级真的让人恼火。在没有sudo的机器上,我还没有找到任何方法来覆盖用户安装的系统范围的安装软件包。这看起来像'sys.path'的组装方式是一个非常严重的缺陷。 – kynan 2013-01-12 18:40:28

1

我已经做了类似如下的运行顶级的Python可执行文件时,预先考虑到系统路径:

import sys 
sys.path = ["<your python path>"] + sys.path 

通常情况下,"<your python path>"对我来说涉及使用__file__属性做相对看看为包含我的项目的顶级模块的路径启用。这不建议用于生产鸡蛋,虽然我似乎不介意后果。 __file__可能有另一种选择。

1

考虑使用-S命令行选项来禁止*.pth处理:

python -c 'import sys; print("\n".join(sys.path))' 
python -S -c 'import sys; print("\n".join(sys.path))' 

https://docs.python.org/3/library/site.html#site.main

您还可以使用-Ssite.main()延迟*.pth处理,直到运行时,说能把握住原创SYS。用于追加路径:从显性空PYTHONPATH

  • 追加

    export PYTHONPATH=$(
        PYTHONPATH='' \ 
        python -c 'import sys; \ 
        sys.path.extend(sys.argv[1:]); old=list(sys.path); \ 
        import site; site.main(); \ 
        [ old.append(p) for p in sys.path if p not in old ]; \ 
        sys.path=old; \ 
        print ":".join(sys.path)' \ 
        $EXTRA_PATH $ANOTHER_PATH) 
    
    python -S ... # using explicit PYTHONPATH 
    
    • 开始以明确的sys.path与扩展
    • 导入网站和呼叫site.main()
    • 追加到旧路径的新路径,然后进行安装in sys.path
    • 用“:”打印为PYTHONPATH
    • python -S是希望以后只运行使用$PYTHONPATH
    • python -S可以同时设定PYTHONPATH(取决于是否需要延长的sys.path之前扩大了)