为什么我需要每个级别的初始化?

2024-03-28 17:39:37 发布

您现在位置:Python中文网/ 问答频道 /正文

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

.
\---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

如果I echo "" > foo/__init__.py,则上述命令有效。

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

更新

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


Tags: 模块pyimport路径目录moststringfoo
1条回答
网友
1楼 · 发布于 2024-03-28 17:39:37

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

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。通过在第一级提供最有用的对象(类/函数),您很有可能记录模块,从而消除用户/开发人员的嵌套导入。。。实际上要尽可能简单地使用,与java导入相反

问题更新后编辑

默认导入程序/查找程序(检查sys.meta_path)是:

  1. BuiltinImporter-搜索/加载内置模块
  2. FrozenImporter-搜索/加载冻结模块(例如.*.pyc)
  3. PathFinder-你感兴趣的,允许搜索/加载基于文件系统的模块

第三个是__init__.py的东西(实际上也是冻结导入器)。

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(和加载器),您可以加载任何文件,例如,不管它在哪里。这给了你巨大的力量。例如,查看^{},根据SO的搜索结果公开代码。

相关问题 更多 >