使用 __init__.py

66

我很难理解在我的项目中,Python的__init__.py文件的使用场景或设计目标。

假设我有一个'model'目录(称为一个包),其中包含以下文件:

  1. __init__.py
  2. meta.py
  3. solrmodel.py
  4. mongomodel.py
  5. samodel.py

我发现了两种使用__init__.py的方法:

  1. 我有一个通用的定义需要在solrmodel.pymongomodel.pysamodel.py中使用。我可以将__init__.py作为所有*model.py类的基础/通用定义吗?这意味着我必须导入model/__init__.py

  2. 或者,__init__.py应该导入其自身中solrmodel.py、mongomodel.py、samodel.py的定义,它允许轻松导入类或函数,如下所示:

  3. # file: __init__.py
    
    from mongomodel import *
    from solrmodel import *
    from samodel import *
    

    我知道import *不被推荐使用,但我只是按照惯例使用它。

    我无法决定上述两种情况之间的区别。是否有更多使用__init__.py的场景,并且您能否解释一下其用途?


1
似乎stackoverflow在渲染markdown时出现了问题。在编辑时显示_init.py,但在显示时却显示_init.py。有人能修复_init_.py的约定吗? - user90150
12
使用反引号将其放入代码块中,像这样:\init.py`。或者使用反斜杠,例如 \_\_init\_\_.py` 代表 __init__.py。下划线用于斜体。 - Ponkadoodle
2个回答

52

我写的大多数__init__.py文件都是空的,因为许多软件包不需要初始化。

有一种情况是我可能需要初始化,就是在软件包加载时我想要一次性读入一堆数据(比如从文件、数据库或网络中读取),这种情况下最好将读取操作放在软件包的__init__.py文件中的一个私有函数中,而不是创建一个单独的“初始化模块”并且在每个实际模块中重复地导入该模块(毫无意义和容易出错:显然依赖于语言保证软件包的__init__.py在任何模块之前被加载是更加Pythonic的方式!)

对于其他具体的、权威性的观点,请查看Python标准库中各个软件包采用的不同方法。


2
Pylons建议将模型放在__init__.py中。这样做可以吗?那样真的会以那种方式初始化模型吗? - user90150
8
个人而言,我更倾向于不在__init__.py中放置大量的代码,但没有深层次的原因避免这样做——这纯粹是一种风格选择。该文件中的所有代码都会在第一次导入包或包中的任何模块时执行。 - Alex Martelli
我有一个关于Django视图中全局变量的问题。您可以提供您的看法吗?https://dev59.com/71kS5IYBdhLWcg3ww45d - Pankaj Singhal

23

当你在包内导入一个模块时,__init__.py 的内容也会被导入。

你忽略了第三种情况,即将公共部分放在一个单独的模块中,然后让其他模块导入该模块,留出 __init__.py 来处理将要在包外部使用的事物。这是我通常遵循的做法。


2
我不太理解。能否请您提供第三种情况的示例? - Tyler Liu
4
@Tyler Long,他的意思是在包中使用单独的初始化模块(例如bootstrap),并在包的__init__.py中调用import bootstrap - warvariuc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接