关于python:为什么我需要每个级别的__init__.py?

Why do I need __init__.py at every level?

本问题已经有最佳答案,请猛点这里访问。

假设我有以下目录结构,其中.是当前工作目录

1
2
3
4
5
.
\---foo
    \---bar
        \---__init__.py
        \---baz.py

当我运行python -c"import foo.bar.baz"时,我得到

1
2
3
Traceback (most recent call last):
  File"<string>", line 1
ImportError: No module named foo.bar.baz

如果我是echo""> foo/__init__.py的话,上面的命令就行了。

我是做了什么错事还是误解了__init__.py的观点?我认为应该停止不应该存在的模块,例如一个名为string的目录,但是如果在我的示例中用string替换foo,我似乎被迫创建一个永远不应该使用的模块,这样我就可以引用层次结构中更深层的文件。

更新

我正在使用一个为我生成__init__.py的构建系统,并且正在强制执行目录结构,虽然我可能会弄乱层次结构,但我宁愿自己添加__init__.py。为了稍微改变这个问题,为什么我需要在每个级别都有一个Python包,而不只是在顶部?这只是一个规则,您只能从python路径或从python路径外的一系列包中导入模块吗?


是的,如果要将目录视为模块,则需要此文件。

The __init__.py files are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path. In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable, described later.

https://docs.python.org/3/tutorial/modules.html包

我尝试创建非空的__init__.py。您有很大的可能性来记录模块,通过在第一层提供最有用的对象(类/函数)来消除用户/开发人员的嵌套导入………实际上是尽可能简单地使用,与之相反的是——比如说,Java导入

问题更新后编辑

默认的导入者/查找者(检查sys.meta_path)是:

  • 内置导入程序-搜索/加载内置模块
  • FrozenImporter-搜索/加载冻结模块(例如*.pyc)
  • 探路者-你感兴趣的人,允许搜索/加载基于文件系统的模块
  • 第三个是__init__.py东西(实际上也是冷冻进口商)。

    docx1〔3〕在来自sys.path的路径(和包中定义的__path__的路径)中搜索模块。该模块可以是独立的python文件(如果它在搜索路径的根目录中)或带有__init__.py的目录。

    参考您的示例:

    1
    2
    3
    4
    foo/
      bar/
        __init__.py
        baz.py
    • 如果您在foo/中创建_init__.pyfoo.bar.baz将可用(如您所说)。

    • 如果您将foo/添加到sys.path或通过PYTHONPATH=foo/传递,bar.baz将可用(注意没有父模块foo)。

    • 如果您编写自己的finder(和loader),那么您可以加载任何文件,例如,不管它在哪里。这给了你很大的力量。例如,查看stack-overflow-import,根据so的搜索结果显示代码。