Python中init.py文件的作用

技术背景

在Python中,__init__.py 文件曾经是Python包(在Python 3.3之前的“常规包”)的必要组成部分。Python定义了两种类型的包:常规包和命名空间包。常规包通常是一个包含 __init__.py 文件的目录,当导入该包时,__init__.py 文件会被隐式执行,其定义的对象会绑定到包的命名空间中。而从Python 3.3开始,引入了隐式命名空间包(PEP 420),不再要求使用 __init__.py 文件来定义可导入的Python包。

实现步骤

标记目录为Python包

如果目录结构如下:

mydir/
    spam/
        __init__.py
        module.py

mydir 在Python的搜索路径中时,可以使用以下方式导入 module.py 中的代码:

import spam.module

或者

from spam import module

若移除 __init__.py 文件,Python将不再将该目录视为包,尝试导入模块将会失败。

包级变量定义与便捷导入

在包中频繁使用的对象可以在 __init__.py 中定义,方便其他模块导入。例如,有如下包结构:

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()

使用 __all__控制导入

__init__.py 中的 __all__ 变量可以控制使用 from package import * 时导入的子模块。例如,在 subPackage_b__init__.py 中:

__all__ = ['module_n2', 'module_n3']

当执行 from package_x.subPackage_b import * 时,只有 module_n2module_n3 会被导入。

核心代码

定义包级变量

# database/__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)

使用 __all__控制导入

# subPackage_b/__init__.py
__all__ = ['module_n2', 'module_n3']

包初始化代码

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

最佳实践

  • 保持 __init__.py 简洁:遵循“显式优于隐式”的原则,避免在 __init__.py 中写入过多复杂代码。
  • 使用 __all__ 控制导入:当需要控制 from package import * 的行为时,使用 __all__ 变量明确指定要导入的子模块。
  • 定义常用对象:将频繁使用的对象定义在 __init__.py 中,方便其他模块导入。

常见问题

Python 3.3之后是否还需要 __init__.py

从Python 3.3开始,__init__.py 不再是定义可导入Python包的必需文件,但为了明确指示该目录是一个包,建议仍然包含它,即使它是空的。

如何在Python 2中加载同级文件

在Python 2中,如果要加载同级文件,可以将当前文件的父目录添加到系统路径中:

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

import cheese
from vehicle_parts import *

不过,建议尽量使用 __init__.py 文件来管理包。

相关文章

python引用外部代码的import机制

【导读】使用import导入额外代码经常报错?看完文章完美解决。▍目录python引用外部代码的方式绝对导入和相对导入结尾▍python引用代码的方式Python中引入代码包的方式包括绝对导入和相对导...

Python动态导入核心解析:按需加载模块的工程实践方案

喜欢的条友记得关注、点赞、转发、收藏,你们的支持就是我最大的动力源泉。根据Python官方性能测试,动态导入机制可使大型应用启动时间缩短35%-68%。本文通过6个生产案例,解析importlib模块...

python之包与模块

包的定义包:就是文件夹,包中还可以有包,即子文件夹,__init__.py是每一个python包必须存在的文件模块:一个个的python文件就是模块包----> 模块 ----> 函数包的...

7行代码,彻底告别python第三方包import导入问题!

最近有不少小伙伴咨询小叮当关于pyton第三方包导入的问题,今天我们就来聊聊第三方包导入那些事。随着对python学习的渐入臻境,越来越多的小伙伴们开始导入自己所需的第三方包,实现各种各样的功能。但是...

Python异常模块和包

异常当检测到一个错误时,Python解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的“异常”, 也就是我们常说的BUG例如:以`r`方式打开一个不存在的文件。f = open('...

详解python包中的__init__.py

详解python包中的__init__.py1、 包与模块,类,函数之间的关系随着互联网和IOT的发展,我们在享受软件的强大和智能的同时,其背后与之对应的代码规模也越来越大。因此我们无法将所有的功能代...