如何阻止 python 加载 'wrong' 包?

How can I keep python from loading the 'wrong' package?

显然,在我们的 Python/2.7.2 环境中加载了一个名为 CrossMap 的包,它有一个子包 tabix。当我启动此版本的 python 和 import tabix 时,tabix 显示: /hpcf/apps/python/install/2.7.2/lib/python2.7/site-packages/CrossMap-0.1.6-py2.7-linux-x86_64.egg/tabix/__init__.pyc 表明它正在从 CrossMap 加载。现在,即使我 pip install pytabix(在 site-packages 目录中创建了一个 tabix.so 文件),它仍然命中 CrossMap 版本。我什至尝试使用 pip install --user pytabix 安装 pytabix 本地化,但它仍然加载 CrossMap 版本。

如何将 import tabix 指向 tabix.so 文件而不是 CrossMap 的子包?

更新:即使在将 CrossMap 移动到 'old_versions' 目录后,当我尝试加载 tabix 时,它仍然会遇到另一个包含 tabix 作为子包的包.当我 import tabix 然后 运行 tabix 时,我从 RSeQC-2.6.1 得到了一个 pysam 包,即使我有 pytabix 因为它在主 [=21] 中是自己的包=] 目录。 pysam 包也会发生同样的事情。这里有什么想法吗?

您可以尝试将 pytabix 安装到不同的文件夹 pip install --target="/path/to/your_new_path" pytabix 并将此新路径添加到 sys.path:

import sys sys.path.insert(0, "/path/to/your_new_path")

然后导入 import your_new_path.tabix

您似乎需要将 pytabix 放在 sys.path 中较早出现的目录中,或者将 CrossMap 移动到路径下方的目录中。

我喜欢偏爱 pytabix 的想法。如果可以:

  1. 修改您的 shell (/etc/bash.bashrc) 的系统配置文件以包含如下内容:export PYTHONPATH=$HOME/stuff/onpythonpath
  2. 使用pip install --target="$HOME/stuff/onpythonpath" pytabix

修改系统范围的配置文件应该将新路径放在 sys.path 的早期。

另一种更喜欢 pytabix 的方法是以可编辑模式安装它。在我的系统中,首先将新安装的软件包放在 sys.path:

例如: 我之前的路径(其中包括通过在配置文件中导出 PYTHONPATH 添加的 "onpythonpath"):

 ['',
  '/usr/local/bin',
  '/home/keith/devel/onpythonpath',
  '/usr/lib/python2.7',
  '/usr/lib/python2.7/plat-x86_64-linux-gnu',
  '/usr/lib/python2.7/lib-tk',
  '/usr/lib/python2.7/lib-old',
  '/usr/lib/python2.7/lib-dynload',
  '/usr/local/lib/python2.7/dist-packages']

现在 运行 之后:

pip install -e git+https://github.com/slowkow/pytabix.git@40e7a78ba6fdfbf72a25da718f530e7c1bad389e#pytabix

这是我的路径:

['',
 '/usr/local/bin',
 '/home/keith/src/pytabix',
 '/home/keith/devel/onpythonpath',
 '/usr/lib/python2.7',
 '/usr/lib/python2.7/plat-x86_64-linux-gnu',
 '/usr/lib/python2.7/lib-tk',
 '/usr/lib/python2.7/lib-old',
 '/usr/lib/python2.7/lib-dynload',
 '/usr/local/lib/python2.7/dist-packages']

您可以使用 python 版本的 site-packages 文件夹中的 .pth 文件为用户手动排序 sys.patheasy_install 也使用它向您的路径添加鸡蛋内容。

导入任何模块时,它首先会查看当前目录, 之后它开始查看系统路径,按照它们出现的顺序(时间顺序), 使用 :

检查
import sys 
print sys.path

因此,初学者的方法是交换列表元素,并将我们需要首先导入的路径放在第 0 个索引处,(交换列表) 为了理解这个概念,可以做上面的事情。 (在实际实施中从来都不是一个好方法)

或者如果您可以在导入之前附加路径

import sys
# the PackageFolder dir contains foo.py, bar.py 
sys.path.append('/foo/bar/PackageFolder')

from foo import ChocolateClass
from bar import RunClass,WalkClass

更好的方法是指定要导入模块的路径:

import bar
foo = bar.load_source('module.name', '/path/to/file.py')
foo.MyClass()

已编译的 Python 文件和 DLL 有等效的便利函数。 对于 Python 3.3+,这有点复杂,不幸的是:

import importlib.bar
loader = importlib.bar.SourceFileLoader("module.name", "/path/to/file.py")
foo = loader.load_module()
foo.MyClass()

希望这对您有所帮助。

我建议您为您的项目使用 virtualenv。 Virtualenv 是避免命名空间污染和您所遇到的争用的绝佳方法。

要调试不知道特定模块隐藏位置的情况,可以尝试在交互式 Python shell 中导入特定模块并打印 __file__ 属性 用于模块。但并非在所有情况下都有效,例如压缩模块,但可以帮助您入门。

据我所知,解决这个问题的最干净的方法是由虚拟机管理程序(如 Vagrant)提供的完全隔离,而不是 virtualenv.[=16= 提供的部分隔离]

我不知道你是否熟悉virtualenv,但它的问题是它只提供python级别的隔离。对于依赖于系统库的 python 包,仅隔离这些包的 python 级部分。 tabixpysam 似乎都具有系统级依赖性。因此,创建一个没有安装 CrossMap 的干净虚拟环境应该可以解决问题。

这对您来说是否真的是一个可行的解决方案是另一回事。我只是想我会提出我的两分钱,因为其他提议的解决方案似乎不适合您。我也只是个人认为,与乱用 sys.path 或手动设置模块以指向某些文件相比,这是解决您问题的更好、更清晰的解决方案。

Vagrant 非常容易设置,并且是整个团队在同一环境中工作的一种非常简单的方法,使用他们习惯的主机上的自己的工具。有关详细信息,请参阅 http://docs.vagrantup.com/v2/getting-started/index.html