我正在创建一个更大的逻辑包,分布在许多目录中,如下所示:
[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
这样做的目的是:
^{pr2}$在.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有一些我没有考虑的副作用。在
具体的非工作行为是,PYTHONPATH在脚本运行后似乎被正确地构造(在PowerShell中的.bashrc
等效中),也就是说,我可以从Python中调试print 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代码段。在
所以,这就是最终的问题。事实证明,
pkgutils.extend_path
将适用于扩展逻辑包中的每个模块,只要它包含在PYTHONPATH
中该逻辑包的第一个实例中。在这两个环境中,PYTHONPATH
前面都有一个environment
模块,它包含extend_path
。在Windows环境中,这个预先添加的路径实际上并不包含任何内容。我的失败基本上是没有意识到extend_path
将扩展到PYTHONPATH
中的所有逻辑包,即使该逻辑包中的特定模块不包含extend_path
,只要第一个实例包含pkgutils
片段。在相关问题 更多 >
编程相关推荐