我正在创建一个较大的逻辑包,分布在许多目录中,如下所示:

[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有一些我没有考虑的副作用。

特定的无效行为是运行该脚本后(在PowerShell中的.bashrc等效项中)PYTHONPATH似乎正确构建,即我可以从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不应附加到模块路径,除非我明确声明。我想知道的是,为什么无论是否包含pkgutils片段,Ubuntu上都不会发生异常(换句话说,为什么它会在未显式声明的情况下追加到模块路径中)。

最佳答案

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

09-04 15:49