繁体   English   中英

Python 导入优先级:包还是模块?

[英]Python import precedence: packages or modules?

我不清楚如何正确命名这个问题。

案例一

假设我有以下目录结构。

foo
|
+- bar/__init__.py
|
+- bar.py

如果我有

from foo import bar

我如何知道正在导入哪个栏( bar.pybar/__init__.py )? 有没有什么简单的方法可以自动检测到这种情况的发生?

案例二

foo
|
+- foo.py
|
+- other.py

如果 other.py 有这条线

import foo

我如何知道正在导入哪个 foo(foo 或 foo.foo)? 同样,是否有任何简单的方法可以自动检测到这种情况的发生?

TLDR; 如果包在同一目录中,则包优先于同名模块。

从文档:

“当导入名为spam的模块时,解释器spam.py在当前目录中搜索名为spam.py的文件,然后在环境变量PYTHONPATH指定的目录列表中搜索。这与 shell 变量 PATH 具有相同的语法,即是,目录名称列表。”

这有点误导,因为解释器还会寻找一个名为spam的包(一个名为spam的目录,其中包含一个__init__.py文件)。 由于目录条目在搜索之前被排序,如果包在同一个目录中,包优先于同名模块,因为spamspam.py之前。

请注意,“当前目录”是相对于主脚本路径(其中__name__ == '__main__' is True路径)。 因此,如果您在/home/billg调用/foo/bar.py ,“当前目录”是指/foo

从 python 外壳:

from foo import bar

print bar.__file__

应该告诉你哪个文件被导入了

罗布

包(带有__init__.py目录)优先于模块。 这个事实的文档很难找到,但你可以在源代码中看到这个: python 2.7python 3.6 (感谢@qff 的发现)。

您还需要 foo 目录中的__init__.py才能让您的示例工作。

如果other.pyfoo/内,那么它将加载foo.py (不是目录foo/ ),因为它会首先查看当前目录(除非您已经使用过 PYTHONPATH 或 sys.path)。

我想补充已接受的答案。 对于Python 3.3+ ,引入了命名空间包,根据PEP 420的导入顺序如下:

在导入处理期间,导入机制将继续迭代父路径中的每个目录,就像在 Python 3.2 中一样。 在查找名为"foo"的模块或包时,对于父路径中的每个目录:

  • 如果找到<directory>/foo/__init__.py ,则导入并返回常规包。
  • 如果没有,但是<directory>/foo.{py,pyc,so,pyd}被找到,一个模块被导入并返回。 确切的扩展列表因平台以及是否指定了-O标志而异。 这里的列表具有代表性。
  • 如果没有,但是<directory>/foo被找到并且是一个目录,它被记录下来并且扫描继续在父路径中的下一个目录。
  • 否则,扫描将继续使用父路径中的下一个目录。

如果扫描完成而没有返回模块或包,并且至少记录了一个目录,则创建一个命名空间包。

在第一种情况下,您尝试从文件“foo.py”导入功能栏

在第二个你试图导入文件 'foo.py'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM