在PYTHONPATH环境变量之前的路径中的鸡蛋

时间:2011-05-12 21:10:01

标签: python setuptools easy-install

如果我从 easy_install 安装了软件包,那么在sys.path变量中的项目之前,鸡蛋会被PYTHONPATH前置。

例如,如果我在当前目录中安装了名为 foo 的鸡蛋包以及名为 foo 的包,那么请执行以下操作:

PYTHONPATH="." python
>>> import foo

这将使用foo的egg版本而不是本地目录。检查sys.path表示鸡蛋放在之前来自PYTHONPATH的项目。这似乎破了。有没有办法覆盖这种行为?

3 个答案:

答案 0 :(得分:13)

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

每次easy_install运行时,它都会重新生成文件easy_install.pth。这是一个快速脚本,您可以在easy_install之后运行,以从easy_install.pth中删除页眉和页脚。您可以创建一个包装器shell脚本,以便在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 - 修改行。

答案 1 :(得分:2)

考虑使用-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

您还可以-S使用site.main()*.pth处理延迟到运行时,比如捕获原始的sys.path以进行追加:

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
  • 从显式空PYTHONPATH
  • 开始
  • 使用extend
  • 显式附加到sys.path
  • 导入网站并致电site.main()
  • 将新路径附加到旧路径,然后将其安装在sys.path
  • 使用"打印:" PYTHONPATH
  • python -S仅适用于以后仅使用$PYTHONPATH
  • 运行 设置python -S时,
  • PYTHONPATH可能是可取的,也可能不合适(取决于在扩展之前是否需要扩展sys.path)

答案 2 :(得分:1)

在运行顶级python可执行文件时,我已经做了类似以下的操作,以便在系统路径前添加:

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

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