__init__.py 是做什么的?

2024-11-18 08:41:00
admin
原创
37
摘要:问题描述:__init__.pyPython 源目录中的用途是什么?解决方案 1:它曾经是软件包 (旧的、 3.3 之前的“常规软件包”,而不是较新的 3.3+“命名空间软件包” )的必需部分。这是文档。Python 定义了两种类型的包,即常规包和命名空间包。常规包是 Python 3.2 及更早版本中存在的...

问题描述:

__init__.pyPython 源目录中的用途是什么?


解决方案 1:

它曾经是软件包 (旧的、 3.3 之前的“常规软件包”,而不是较新的 3.3+“命名空间软件包” )的必需部分。

这是文档。

Python 定义了两种类型的包,即常规包和命名空间包。常规包是 Python 3.2 及更早版本中存在的传统包。常规包通常实现为包含文件的目录__init__.py。导入常规包时,__init__.py会隐式执行此文件,并且其定义的对象将绑定到包命名空间中的名称。该__init__.py文件可以包含任何其他模块可以包含的相同 Python 代码,并且 Python 会在导入模块时向其添加一些附加属性。

但只需单击链接,它包含一个示例、更多信息和命名空间包的解释(没有__init__.py.

解决方案 2:

命名的文件__init__.py用于将磁盘上的目录标记为 Python 包目录。如果您有文件

mydir/spam/__init__.py
mydir/spam/module.py

并且位于您的路径中,您可以导入mydir代码module.py

import spam.module

或者

from spam import module

如果删除该__init__.py文件,Python 将不再查找该目录内的子模块,因此导入该模块的尝试将失败。

__init__.py文件通常是空的,但可用于以更方便的名称导出包的选定部分,保存便利函数等。根据上述示例,init 模块的内容可以按如下方式访问

import spam

此答案基于此网页。

解决方案 3:

除了将目录标记为 Python 包并定义 之外__all____init__.py还允许您在包级别定义任何变量。如果包以类似 API 的方式定义了一些将频繁导入的内容,那么这样做通常很方便。这种模式促进了对 Pythonic“扁平优于嵌套”理念的坚持。

一个例子

下面是我的一个项目中的示例,在这个项目中,我经常导入一个sessionmaker调用Session来与我的数据库交互。我编写了一个包含几个模块的“数据库”包:

database/
    __init__.py
    schema.py
    insertions.py
    queries.py

我的__init__.py包含以下代码:

import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)

由于我在这里定义Session,我可以使用下面的语法启动一个新会话。此代码在“数据库”包目录内部或外部执行都是一样的。

from database import Session
session = Session()

当然,这只是一个小小的便利——另一种方法是Session在我的数据库包中定义一个新文件,如“create_session.py”,然后使用以下命令启动新会话:

from database.create_session import Session
session = Session()

进一步阅读

reddit 上有一篇非常有趣的帖子讨论了__init__.py这里的适当用法:

http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/

大多数人的观点似乎是__init__.py文件应该非常薄,以避免违反“显式优于隐式”的理念。

解决方案 4:

主要有两个原因__init__.py

  1. 为了方便:其他用户不需要知道您的函数在包层次结构(文档)中的确切位置。

your_package/
  __init__.py
  file1.py
  file2.py
    ...
  fileN.py
# in __init__.py
from .file1 import *
from .file2 import *
...
from .fileN import *
# in file1.py
def add():
    pass

然后其他人可以通过以下方式调用 add()

 from your_package import add

不知道 file1 的内部函数,例如

 from your_package.file1 import add
  1. 如果您想要初始化某些内容;例如,日志记录(应放在顶层):

 import logging.config
 logging.config.dictConfig(Your_logging_config)

解决方案 5:

__init__.py文件使 Python 将包含它的目录视为模块。

此外,这是模块中第一个被加载的文件,因此您可以使用它来执行每次加载模块时要运行的代码,或者指定要导出的子模块。

解决方案 6:

从 Python 3.3 开始,__init__.py不再需要将目录定义为可导入的 Python 包。

检查PEP 420:隐式命名空间包:

本机支持不需要__init__.py标记文件且可以自动跨越多个路径段的包目录(受到PEP 420中所述的各种第三方命名空间包方法的启发)

测试如下:

$ mkdir -p /tmp/test_init
$ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
├── module.py
└── __init__.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

$ rm -f /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
└── module.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

参考文献:

https://docs.python.org/3/whatsnew/3.3.html#pep-420-implicit-namespace-packages

https://www.python.org/dev/peps/pep-0420/

Python 3 中的包不需要 __init__.py 吗?

解决方案 7:

尽管 Python 不需要__init__.py文件就能工作,但你仍然应该包含一个文件。

它指定该目录应被视为一个包,因此将其包括在内(即使它是空的)。

还有一种情况你实际上可能会使用__init__.py文件:

假设您有以下文件结构:

main_methods 
    |- methods.py

methods.py包含以下内容:

def foo():
    return 'foo'

要使用,foo()您需要以下之一:

from main_methods.methods import foo # Call with foo()
from main_methods import methods # Call with methods.foo()
import main_methods.methods # Call with main_methods.methods.foo()

也许您需要(或想要)保留methods.py内部main_methods(例如运行时/依赖项)但您只想导入main_methods


如果您将名称更改methods.py为,则只需导入__init__.py即可使用:foo()`main_methods`

import main_methods
print(main_methods.foo()) # Prints 'foo'

这是有效的,因为__init__.py它被视为包的一部分。


一些 Python 包确实会这样做。一个例子是JSON,其中运行import json实际上是__init__.pyjson包中导入(请参阅此处的包文件结构):

源代码: Lib/json/__init__.py

解决方案 8:

在 Python 中,包的定义非常简单。与 Java 一样,层次结构和目录结构是相同的。但是你必须有一个包。我将使用下面的示例__init__.py解释该文件:__init__.py

package_x/
|--  __init__.py
|--    subPackage_a/
|------  __init__.py
|------  module_m1.py
|--    subPackage_b/
|------  __init__.py
|------  module_n1.py
|------  module_n2.py
|------  module_n3.py

__init__.py可以为空,只要存在即可。表示该目录应视为一个包。当然__init__.py也可以设置相应的内容。

如果我们在module_n1中添加一个函数:

def function_X():
    print "function_X in module_n1"
    return

运行后:

>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()

function_X in module_n1 

然后我们按照层次结构包并调用 module_n1 函数。我们可以__init__.py在 subPackage_b 中像这样使用:

__all__ = ['module_n2', 'module_n3']

运行后:

>>>from package_x.subPackage_b import * 
>>>module_n1.function_X()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_n1

因此使用*导入,模块包取决于__init__.py内容。

解决方案 9:

__init__.py将会把它所在的目录视为可加载模块。

对于喜欢阅读代码的人,我把Two-Bit Alchemist 的评论放在这里。

$ find /tmp/mydir/
/tmp/mydir/
/tmp/mydir//spam
/tmp/mydir//spam/__init__.py
/tmp/mydir//spam/module.py
$ cd ~
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
>>> module.myfun(3)
9
>>> exit()
$ 
$ rm /tmp/mydir/spam/__init__.py*
$ 
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named spam
>>> 

解决方案 10:

它便于导入其他 python 文件。当您将此文件放在包含其他 py 文件的目录(例如 stuff)中时,您可以执行类似 import stuff.other 的操作。

root\n    stuff\n         other.py

    morestuff\n         another.py

如果目录 stuff 中没有这个__init__.py,您就无法导入 other.py,因为 Python 不知道 stuff 的源代码在哪里,也无法将其识别为包。

解决方案 11:

文件__init__.py使导入变得简单。当__init__.py包中存在时,a()可以从文件中导入函数b.py,如下所示:

from b import a

但是如果没有它,您就无法直接导入。您必须修改系统路径:

import sys
sys.path.insert(0, 'path/to/b.py')

from b import a

解决方案 12:

__init__.py 允许将模块转换为包,而不会破坏 API 或创建多余的嵌套命名空间或私有模块*。当我想扩展命名空间时,这会很有帮助。

如果我有一个文件 util.py 包含

def foo():
    ...

然后用户将foo访问

from util import foo

如果我想添加用于数据库交互的实用函数,并且希望它们在 下有自己的命名空间util,我需要一个新目录*,并且为了保持 API 兼容性(以便from util import foo仍然有效),我将其命名为 util/。我可以*将 util.py 移动到 util/,如下所示,

util/
  __init__.py
  util.py
  db.py

在 util/__init__.py 中执行

from util import *

但这是多余的。我们不需要使用 util/util.py 文件,只需将 util.py 内容放在 __init__.py 中,用户就可以

from util import foo
from util.db import check_schema

我认为这很好地突出了包的 __init__.py 与模块util的类似作用util

  • 其他答案中也提到了这一点,但我想在这里强调一下

** 无需使用导入技巧。请注意,创建与文件同名的新包是行不通的,请参阅此

解决方案 13:

__init__.py:它是位于包目录中的 Python 文件,在导入包或包中的模块时会调用它。您可以使用它来执行包初始化代码,即,每当导入包时,都会先执行 Python 语句,然后再执行此文件夹中的其他模块。它类似于 c 或 Java 程序的主函数,但它存在于 Python 包模块(文件夹)中,而不是核心 Python 文件中。__init__.py当模块导入 Python 文件时,它还可以访问此文件中定义的全局变量。

例如,

__init__.py在一个名为的文件夹中有一个名为的文件pymodlib,该文件包含以下语句:

print(f'Invoking __init__.py for {__name__}')
pystructures = ['for_loop', 'while__loop', 'ifCondition']

pymodlib当我在解决方案模块或笔记本或 Python 控制台中导入此包时:

导入时会执行这两个语句。因此,在日志或控制台中,您将看到以下输出:

>>> import pymodlib
Invoking __init__.py for pymodlib

在 python 控制台的下一个语句中:我可以访问全局变量:

>> pymodlib.pystructures

它给出以下输出:

['for_loop', 'while__loop', 'ifCondition']

现在,从 Python 3.3 开始,此文件的使用已成为可选的,以使文件夹成为 Python 模块。因此,您可以跳过将其包含在 Python 模块文件夹中的步骤。

解决方案 14:

如果您使用的是 Python 2 并且想要加载文件的同级文件,您只需将文件的父文件夹添加到会话的系统路径中即可。它的行为与当前文件是初始化文件时的行为大致相同。

import os
import sys
dir_path = os.path.dirname(__file__)
sys.path.insert(0, dir_path)

此后,相对于文件目录的常规导入就可以正常工作。例如

import cheese
from vehicle_parts import *
# etc.

虽然通常情况下,你会希望使用正确的init .py 文件,但在处理遗留代码时,你可能会被困在例如一个硬编码的库中,该库仅用于加载特定文件。对于这些情况,这是一种替代方案。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   681  
  在项目管理领域,集成产品开发(IPD)流程以其高效、协同的特点,被众多企业视为提升产品竞争力的关键。IPD流程强调跨部门、跨职能的紧密合作,以确保产品从概念到市场各个环节的无缝衔接。然而,实现这一目标并非易事,它需要企业深刻理解并掌握IPD流程中的跨部门协作艺术。本文将深入探讨IPD流程中跨部门协作的三个关键点,旨在为...
IPD项目管理咨询   9  
  掌握IPD流程图:提升团队协作的关键路径在当今快速变化的商业环境中,团队协作的效率与效果直接关系到项目的成功与否。集成产品开发(Integrated Product Development,简称IPD)作为一种先进的研发管理理念,通过跨部门、跨领域的协同工作,能够显著提升产品开发的速度与质量。而IPD流程图,则是这一理...
IPD流程阶段   9  
  IPD流程概述:理解其核心价值与实施背景集成产品开发(Integrated Product Development,简称IPD)是一种先进的产品开发管理理念,它强调跨部门协作、市场导向和快速响应变化的能力。IPD流程不仅关注产品本身的技术创新,更注重将市场、研发、生产、销售等各个环节紧密集成,以实现产品从概念到市场的高...
华为IPD是什么   7  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程以其跨部门协作、高效决策和快速响应市场变化的特点,被众多企业视为提升竞争力的关键。然而,实践IPD流程并非易事,项目管理中的种种错误往往阻碍了其效果的充分发挥。本文旨在深入探讨如何在实施IPD流程时避免这些常见错误,...
IPD框架   7  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用