鉴于以下内容(请注意test
错误地test
包中内置阴影,我应该将其命名为tests
,我们将在问题后面回到这个问题(
├── test
│ └── test_request_billing_id.py
└── requets_billing_id.py
在 Python shell 中时,尝试运行from test import test_request_billing_id
它给出了ImportError: cannot import name 'test_request_billing_id'
,它正在尝试导入内置的test
包而不是我自己的test
文件夹。
这可以通过运行此有效导入来验证
from test import support
问题1:
鉴于 Python3 允许隐式命名空间包,这意味着我的test
文件夹也是一个包,我想内置的test
包比我自己的test
包具有更高的优先级?
问题2:
我在自己的test
文件夹中创建了__init__.py
,如下所示:
├── test
│ ├── __init__.py
│ └── test_request_billing_id.py
└── requets_billing_id.py
并再次运行相同的导入语句,它工作正常。
from test import test_request_billing_id
通过运行此无效导入来验证隐藏内置test
from test import support
给出错误:ImportError: cannot import name 'support'
在我看来,__init__.py
告诉 python 解释器让我的test
影子是内置的test
包。
有人可以解释一下吗,或者这在任何地方都有记录吗?
是的,带有__init__.py
的包优先。这在 PEP 的这一部分中进行了解释:
在进口加工过程中,进口机械将继续 像在 Python 中一样遍历父路径中的每个目录 3.2. 在查找名为 "foo" 的模块或软件包时,对于父路径中的每个目录:
- 如果找到
<directory>/foo/__init__.py
,则导入并返回常规包。- 如果不是,但找到
<directory>/foo.{py,pyc,so,pyd}
,则导入并返回模块。扩展的确切列表因平台而异 以及是否指定了 -O 标志。这里的列表具有代表性。- 如果没有,但找到
<directory>/foo
并且是一个目录,则会记录它,然后继续扫描父目录中的下一个目录 路径。- 否则,扫描将继续使用父路径中的下一个目录。
如果在搜索过程中遇到任何命名空间包,则会"记录"它们并继续搜索。如果稍后找到包含__init__.py
的包,则会丢弃"记录的"命名空间包,而是导入带有__init__.py
的包。
这正是当您的test
包没有__init__.py
时发生的情况 - 标准库中的test
包确实有一个__init__.py
,因此它优先于您的命名空间test
包。