我有一个这样的“规范文件结构”(我给出了合理的名称以便于阅读):
mainpack/
__main__.py
__init__.py
- helpers/
__init__.py
path.py
- network/
__init__.py
clientlib.py
server.py
- gui/
__init__.py
mainwindow.py
controllers.py
在这种结构中,例如,每个包中包含的模块可能希望通过以下内容中的相对导入来访问helpers
实用程序:
# network/clientlib.py
from ..helpers.path import create_dir
使用__main__.py
文件以“脚本”方式运行程序:
python mainpack/
尝试按照我在__main__.py
中输入的PEP 366执行这些行:
___package___ = "mainpack"
from .network.clientlib import helloclient
但在跑步时:
$ python mainpack
Traceback (most recent call last):
File "/usr/lib/python2.6/runpy.py", line 122, in _run_module_as_main
"__main__", fname, loader, pkg_name)
File "/usr/lib/python2.6/runpy.py", line 34, in _run_code
exec code in run_globals
File "path/mainpack/__main__.py", line 2, in <module>
from .network.clientlib import helloclient
SystemError: Parent module 'mainpack' not loaded, cannot perform relative import
怎么了?处理和有效利用相对进口的正确方法是什么?
我也尝试过将当前目录添加到PYTHONPATH,但没有任何更改。
受extraneon和taherh的答案启发,这里有一些代码在文件树上运行,直到它用完构建完整包名的
__init__.py
文件。这绝对是一个黑客,但似乎不管文件在目录树中的深度如何,都可以工作。似乎绝对进口受到了极大的鼓励。加载代码似乎类似于this:
这让我觉得你的模块可能不在sys.path上。如果启动Python(通常)并在提示符下键入“import mainpack”,它会做什么?它应该能找到它。
我自己也试过了,也犯了同样的错误。读了一点之后,我找到了以下解决方案:
我觉得有点老套,但确实管用。技巧似乎是确保包
foo
已加载,以便导入可以是相对的。PEP 366中给出的“样板文件”似乎不完整。尽管它设置了
__package__
变量,但它实际上并不导入包,这也是允许相对导入工作所必需的。 extraneon的解决方案是正确的。注意,仅仅在
sys.path
中包含模块的目录是不够的,需要显式导入相应的包。与PEP 366中给出的示例相比,下面的示例更适合于确保无论如何调用python模块(通过规则的import
,或通过python -m
,或通过python
,从任何位置调用),都可以执行python模块:如果脚本不在包目录的顶层,并且需要导入顶层以下的模块,则必须重复
os.path.dirname
,直到parent_dir
是包含顶层的目录为止。相关问题 更多 >
编程相关推荐