我对python导入有一个奇怪的(对我来说)问题,我想了解它的问题所在。
我创建了一个具有以下目录结构的演示项目:
├── entry.py
└── foo
├── __init__.py
└── bar
├── __init__.py
├── sdk.py
├── service.py
└── utils.py
如果我运行python entry.py
,则在service.py
中,以下语句有效:
from foo.bar import utils
这不是:
import foo.bar.utils as utils
# entry.py:
from foo.bar.sdk import get_sdk
print(get_sdk())
# foo - __init__.py
# empty on purpose
# bar - __init__.py
from .service import Service
# sdk.py
def get_sdk():
return "SDK"
# service.py
import foo.bar.utils as utils # wrong import
# from foo.bar import utils # works!
class Service:
def do_service(self):
util = utils.get_utility_string()
print("Doing service call {}".format(util))
# utils.py
def get_utility_string():
return "This is useful"
通过运行python entry.py
我得到:
Traceback (most recent call last):
File "entry.py", line 1, in <module>
from foo.bar.sdk import get_sdk
File "/Users/paloand/Downloads/p_demo/foo/bar/__init__.py", line 1, in <module>
from .service import Service
File "/Users/paloand/Downloads/p_demo/foo/bar/service.py", line 1, in <module>
import foo.bar.utils as utils
AttributeError: module 'foo' has no attribute 'bar'
据我在entry.py
中的理解,当get_sdk
模块中出现sdk
符号时,也正在导入foo
包。在foo
中导入bar
时,__init__.py
文件请求导入Service
符号。因此,在导入foo
时,service.py
中再次需要它。
在我的Dropbox中链接到上载的演示项目:Demo
我已经阅读了this个问题和所有答案,但是在那里我无法提取任何信息。我也找到了这个bug,但不确定在这里是否适用。我还阅读了python中的common traps导入,但找不到此。
我想了解两者之间的差异以及实际发生的情况。
我正在使用 python 3.6
谢谢
编辑
已更新,并显示错误消息
编辑2
在两种情况下,我都尝试过python -vv entry.py
。相关日志位于粘贴中:https://pastebin.com/J9guMqJS。
在两种情况下,导入顺序都相同,在“不良”情况下,此导入失败:
import 'foo.bar.utils' # <_frozen_importlib_external.SourceFileLoader object at 0x1103ddf28>