我正在创建一个较大的逻辑包,分布在许多目录中,如下所示:
[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__.py
(from 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
中的所有逻辑包。