Python 解释器中的错误,还是我误解了包导入机制?
Bug in Python interpreter or am I misunderstanding package import mechanism?
我有以下源代码树:
planets/
earth.py
mars.py
util.py
main.py
使用以下代码:
planets/earth.py:
def moon() -> None:
print('moon')
planets/mars.py:
def phobos() -> None:
print('phobos')
util.py:
import planets.mars # yes, just this
main.py:
import planets.earth
import util
def foobar() -> None:
planets.mars.phobos()
if __name__ == '__main__':
foobar()
请注意,在 "main.py" 中,我没有明确导入 "planets.mars"。当我 运行 "main.py" 时,我没有像预期的那样收到错误,而是得到了以下输出:
phobos
我好像是因为我在"util.py"中导入"planets.mars",然后在"main.py"中导入"util.py",所以"main.py"可以看到"planets.mars" 因此我可以从 "main.py".
调用 "planets.mars.phobos()"
但是,当我从 "main.py" 中删除 "import planets.earth" 时,我在尝试 运行 "main.py" 时遇到 "NameError: name 'planets' not defined" 异常。这似乎表明 "planets.mars" 通过导入 "util.py" 而被传递导入 "main.py" 并不是发生了什么,真正发生的是我的 [=61= 中存在错误] 口译员。
有人可以为我揭开这个谜团吗?我在 Debian 9 上使用 CPython 版本 3.7.0。
谢谢!
导入 planets.earth
将 planets
模块添加到 main.py
的命名空间,并将 planets
和 planets.earth
插入 sys.modules
。
在 util.py
中导入 planets.mars
会将 planets.mars
插入 sys.modules
并使名称 mars
可用作 planets
的属性。
当planets.mars.phobos
在main.py中访问时,planet.mars
可以通过main.py
的命名空间中的名称planets
访问。
如果从 main.py
中删除 planets.earth
的导入,planets
不再在模块命名空间中,因此会引发 NameError
。
如果删除 util.py
的导入,mars
不会设置为 planets
的属性,因此会引发 AttributeError
。
这种行为可能会造成混淆,这也是为什么许多包都有一个 __init__.py
导入子模块/子包以便在导入包时它们都可用的原因之一。
我有以下源代码树:
planets/
earth.py
mars.py
util.py
main.py
使用以下代码:
planets/earth.py:
def moon() -> None:
print('moon')
planets/mars.py:
def phobos() -> None:
print('phobos')
util.py:
import planets.mars # yes, just this
main.py:
import planets.earth
import util
def foobar() -> None:
planets.mars.phobos()
if __name__ == '__main__':
foobar()
请注意,在 "main.py" 中,我没有明确导入 "planets.mars"。当我 运行 "main.py" 时,我没有像预期的那样收到错误,而是得到了以下输出:
phobos
我好像是因为我在"util.py"中导入"planets.mars",然后在"main.py"中导入"util.py",所以"main.py"可以看到"planets.mars" 因此我可以从 "main.py".
调用 "planets.mars.phobos()"但是,当我从 "main.py" 中删除 "import planets.earth" 时,我在尝试 运行 "main.py" 时遇到 "NameError: name 'planets' not defined" 异常。这似乎表明 "planets.mars" 通过导入 "util.py" 而被传递导入 "main.py" 并不是发生了什么,真正发生的是我的 [=61= 中存在错误] 口译员。
有人可以为我揭开这个谜团吗?我在 Debian 9 上使用 CPython 版本 3.7.0。
谢谢!
导入 planets.earth
将 planets
模块添加到 main.py
的命名空间,并将 planets
和 planets.earth
插入 sys.modules
。
在 util.py
中导入 planets.mars
会将 planets.mars
插入 sys.modules
并使名称 mars
可用作 planets
的属性。
当planets.mars.phobos
在main.py中访问时,planet.mars
可以通过main.py
的命名空间中的名称planets
访问。
如果从 main.py
中删除 planets.earth
的导入,planets
不再在模块命名空间中,因此会引发 NameError
。
如果删除 util.py
的导入,mars
不会设置为 planets
的属性,因此会引发 AttributeError
。
这种行为可能会造成混淆,这也是为什么许多包都有一个 __init__.py
导入子模块/子包以便在导入包时它们都可用的原因之一。