为什么每个级别都需要 __init__.py?
Why do I need __init__.py at every level?
鉴于我有以下目录结构,.
是当前工作目录
.
\---foo
\---bar
\---__init__.py
\---baz.py
当我运行python -c "import foo.bar.baz"
我得到
Traceback (most recent call last):
File "<string>", line 1
ImportError: No module named foo.bar.baz
如果我echo "" > foo/__init__.py
,上面的命令有效。
我是做错了什么还是我误解了__init__.py
的意思?我认为这是在不应该存在的地方停止存在的模块,例如一个名为 string
的目录,但是如果在我的示例中将 foo
替换为 string
,我似乎被迫创建了一个永远不应该使用的模块,这样我就可以引用一个文件层次结构更深。
更新
我正在使用一个构建系统为我生成 __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#packages
在 __init__.py
文件中,您很有可能记录模块,通过提供最有用的对象 (classes/functions)第一层... ...实际上是尽可能简单。
问题更新后编辑
默认importer/finder(检查sys.meta_path
)是:
- BuiltinImporter - 搜索for/load一个内置模块
- FrozenImporter - 搜索 for/loads 冻结模块(例如 *.pyc)
- PathFinder - 你感兴趣的,允许搜索 for/loads 一个基于文件系统的模块
第三个是 __init__.py
东西(实际上也是 FrozenImporter
)。
PathFinder
在 sys.path
的路径中搜索模块(以及在包中定义的 __path__
中)。该模块可以是一个独立的 python 文件(如果它位于搜索路径的根目录中)或带有 __init__.py
.
的目录
参考你的例子:
foo/
bar/
__init__.py
baz.py
如果您在 foo/
中创建 _init__.py
,foo.bar.baz
将可用(如您所说)。
如果将 foo/
添加到 sys.path
或通过 PYTHONPATH=foo/
传递,bar.baz
将可用(注意没有父模块 foo)。
如果您自己编写 finder (and Loader) you can load for example any file you want despite where it is. That gives you great power. For example take a look on stack-overflow-import
,则根据 SO 的搜索结果公开代码。
鉴于我有以下目录结构,.
是当前工作目录
.
\---foo
\---bar
\---__init__.py
\---baz.py
当我运行python -c "import foo.bar.baz"
我得到
Traceback (most recent call last):
File "<string>", line 1
ImportError: No module named foo.bar.baz
如果我echo "" > foo/__init__.py
,上面的命令有效。
我是做错了什么还是我误解了__init__.py
的意思?我认为这是在不应该存在的地方停止存在的模块,例如一个名为 string
的目录,但是如果在我的示例中将 foo
替换为 string
,我似乎被迫创建了一个永远不应该使用的模块,这样我就可以引用一个文件层次结构更深。
更新
我正在使用一个构建系统为我生成 __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#packages
在 __init__.py
文件中,您很有可能记录模块,通过提供最有用的对象 (classes/functions)第一层... ...实际上是尽可能简单。
问题更新后编辑
默认importer/finder(检查sys.meta_path
)是:
- BuiltinImporter - 搜索for/load一个内置模块
- FrozenImporter - 搜索 for/loads 冻结模块(例如 *.pyc)
- PathFinder - 你感兴趣的,允许搜索 for/loads 一个基于文件系统的模块
第三个是 __init__.py
东西(实际上也是 FrozenImporter
)。
PathFinder
在 sys.path
的路径中搜索模块(以及在包中定义的 __path__
中)。该模块可以是一个独立的 python 文件(如果它位于搜索路径的根目录中)或带有 __init__.py
.
参考你的例子:
foo/
bar/
__init__.py
baz.py
如果您在
foo/
中创建_init__.py
,foo.bar.baz
将可用(如您所说)。如果将
foo/
添加到sys.path
或通过PYTHONPATH=foo/
传递,bar.baz
将可用(注意没有父模块 foo)。如果您自己编写 finder (and Loader) you can load for example any file you want despite where it is. That gives you great power. For example take a look on
stack-overflow-import
,则根据 SO 的搜索结果公开代码。