Python搜索路径错误,但仅限于Windows

时间:2013-11-29 14:23:38

标签: python linux windows macos

我正在创建一个扩展到许多目录的更大的逻辑包,如下所示:

[projects root]/projectname1/lib/python/logicalpackage/__init__.py
[projects root]/projectname1/lib/python/logicalpackage/projectname1/__init__.py
[projects root]/projectname2/lib/python/logicalpackage/__init__.py
[projects root]/projectname2/lib/python/logicalpackage/projectname2/__init__.py

我们的想法是能够做到这一点:

import logicalpackage.projectname1 as p1
import logicalpackage.projectname2 as p2

在.bashrc或$ profile(分别为bash和PowerShell)中创建一个脚本后,它将覆盖[projects root]/*/lib/python/并导入它找到的包。

我知道pkgutil用于此目的,方法是将该代码段放在__init__.pyfrom pkgutil import extend_path; __path__ = extend_path(__path__, __name__)中,并且当我这样做时,我可以让所有系统都能正常运行。我的问题是,为什么当我使用pkgutil时,这仍然可以正常工作,但仅限于某些平台 - 特别是在OSX和Ubuntu(我见过的10和12) ,它的工作原理,但在Windows(7)中却没有。我担心的是使用pkgutil会产生一些我不考虑的副作用。

特定的非工作行为是PYTHONPATH在运行该脚本之后似乎是正确构造的(在PowerShell中的.bashrc等价物中),即我可以在Python中调试打印PYTHONPATH并且它与在另一个平台上构建的路径但是,from projectname1 import foo成功,from projectname2 import bar失败(大概是因为projectname2后来被alpha全局化)。这实际上是我没有pkgutil所期望的行为。为什么不是OSX和Ubuntu中的行为?这个问题来自Windows或PowerShell的某些路径机制,还是在Windows上编译的Python二进制文件,还是完全不同的其他东西?

编辑:添加以下内容以获得更清晰:

# d:\projects> [Environment]::SetEnvironmentVariable("PYTHONPATH","d:\\projects\\projectname1\\lib\python;d:\\projects\\projectname2\\lib\\python;")
# d:\projects> echo $env:PYTHONPATH
# d:\\projects\\projectname1\\lib\python;e:\\projects\\projectname2\\lib\\python;
# d:\projects> python

import sys
sys.path
# => ['', '..python install dir..\\lib\\site-packages\\pip-1.2.1-py2.7.egg', 'd:\\projects\\projectname1\\lib\\python', 'd:\\projects\\projectname2\\lib\\python', ...usual stuff...]
import logicalpackage
logicalpackage.__path__
# => ['d:\\projects\\projectname1\\lib\\python\\logicalpackage']
import logicalpackage.projectname1 as p1
import logicalpackage.projectname2 as p2

# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# ImportError: No module named projectname2
# exit()

用上面提到的pkgutils代码替换空__init__.py

# d:\projects> python
import sys
sys.path
# => ['', 'D:\\usr\\Python27_32bit\\lib\\site-packages\\pip-1.2.1-py2.7.egg', 'd:\\projects\\projectname1\\lib\\python', 'd:\\projects\\projectname2\\lib\\python', 'd:\\projects', '...etc...']
import logicalpackage
logicalpackage.__path__
# => ['d:\\projects\\projectname1\\lib\\python\\logicalpackage', 'd:\\projects\\projectname2\\lib\\python\\logicalpackage']
import logicalpackage.projectname1 as p1
import logicalpackage.projectname2 as p2

注意:没有例外。通过pkgutil附加到模块路径后异常消失是预期的行为(对我来说,对the documentation) - 除非我明确声明,否则Python不应附加到模块路径。我想知道为什么在Ubuntu上没有异常(换句话说,为什么它附加到模块路径没有被显式声明),无论我是否包含pkgutils片段。

1 个答案:

答案 0 :(得分:0)

所以,这就是问题所在。事实证明pkgutils.extend_path将适用于扩展逻辑包中的每个模块,只要它包含在PYTHONPATH中该逻辑包的FIRST实例中即可。在这两种环境中,PYTHONPATH都包含environment中包含的logicalpackage模块,其中包含extend_path。在Windows环境中,该前置路径实际上并不包含任何内容。我的失败基本上是没有认识到extend_path将扩展PYTHONPATH中的所有逻辑包,即使该逻辑包中的特定模块不包含extend_path,只要第一个实例包含pkgutils摘要。