浅谈Python __init__.py的作用


Posted in Python onOctober 28, 2020

我们经常在python的模块目录中会看到 "__init__.py"  这个文件,那么它到底有什么作用呢?

1. 标识该目录是一个python的模块包(module package)

如果你是使用python的相关IDE来进行开发,那么如果目录中存在该文件,该目录就会被识别为 module package 。

2. 简化模块导入操作

假设我们的模块包的目录结构如下:

.
└── mypackage
  ├── subpackage_1
  │  ├── test11.py
  │  └── test12.py
  ├── subpackage_2
  │  ├── test21.py
  │  └── test22.py
  └── subpackage_3
    ├── test31.py
    └── test32.py

如果我们使用最直接的导入方式,将整个文件拷贝到工程目录下,然后直接导入:

from mypackage.subpackage_1 import test11
from mypackage.subpackage_1 import test12
from mypackage.subpackage_2 import test21
from mypackage.subpackage_2 import test22
from mypackage.subpackage_3 import test31
from mypackage.subpackage_3 import test32

当然这个例子里面文件比较少,如果模块比较大,目录比较深的话,可能自己都记不清该如何导入。(很有可能,哪怕只想导入一个模块都要在目录中找很久)

这种情况下,__init__.py 就很有作用了。我们先来看看该文件是如何工作的。

2.1 __init__.py 是怎么工作的?

实际上,如果目录中包含了 __init__.py 时,当用 import 导入该目录时,会执行 __init__.py 里面的代码。

我们在mypackage目录下增加一个 __init__.py 文件来做一个实验:

.
└── mypackage
  ├── __init__.py
  ├── subpackage_1
  │  ├── test11.py
  │  └── test12.py
  ├── subpackage_2
  │  ├── test21.py
  │  └── test22.py
  └── subpackage_3
    ├── test31.py
    └── test32.py

mypackage/__init__.py 里面加一个print,如果执行了该文件就会输出:

print("You have imported mypackage")

下面直接用交互模式进行 import

>>> import mypackage
You have imported mypackage

很显然,__init__.py 在包被导入时会被执行。

2.2  控制模块导入

我们再做一个实验,在 mypackage/__init__.py 添加以下语句:

from subpackage_1 import test11

我们导入 mypackage 试试:

>>> import mypackage
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "/home/taopeng/Workspace/Test/mypackage/__init__.py", line 2, in <module>
  from subpackage_1 import test11
ImportError: No module named 'subpackage_1'

报错了。。。怎么回事?

原来,在我们执行import时,当前目录是不会变的(就算是执行子目录的文件),还是需要完整的包名。

from mypackage.subpackage_1 import test11

综上,我们可以在__init__.py 指定默认需要导入的模块

2.3  偷懒的导入方法

有时候我们在做导入时会偷懒,将包中的所有内容导入

from mypackage import *

这是怎么实现的呢? __all__ 变量就是干这个工作的。

__all__ 关联了一个模块列表,当执行 from xx import * 时,就会导入列表中的模块。我们将 __init__.py 修改为 。

__all__ = ['subpackage_1', 'subpackage_2']

这里没有包含 subpackage_3,是为了证明 __all__ 起作用了,而不是导入了所有子目录。

>>> from mypackage import *
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'subpackage_1', 'subpackage_2']
>>> 
>>> dir(subpackage_1)
['__doc__', '__loader__', '__name__', '__package__', '__path__', '__spec__']

子目录的中的模块没有导入!!!

该例子中的导入等价于

from mypackage import subpackage_1, subpackage_2

因此,导入操作会继续查找 subpackage_1 和 subpackage_2 中的 __init__.py 并执行。(但是此时不会执行 import *)

我们在 subpackage_1 下添加 __init__.py 文件:

__all__ = ['test11', 'test12']

# 默认只导入test11
from mypackage.subpackage_1 import test11

再来导入试试

>>> from mypackage import *
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'subpackage_1', 'subpackage_2']
>>> 
>>> dir(subpackage_1)
['__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'test11']

如果想要导入子包的所有模块,则需要更精确指定。

>>> from mypackage.subpackage_1 import *
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'test11', 'test12']

3. 配置模块的初始化操作

在了解了 __init__.py 的工作原理后,应该能理解该文件就是一个正常的python代码文件。

因此可以将初始化代码放入该文件中。

到此这篇关于浅谈Python __init__.py的作用的文章就介绍到这了,更多相关Python __init__.py内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python错误处理详解
Sep 28 Python
python实现带验证码网站的自动登陆实现代码
Jan 12 Python
python strip() 函数和 split() 函数的详解及实例
Feb 03 Python
Python实现接受任意个数参数的函数方法
Apr 21 Python
Tensorflow 同时载入多个模型的实例讲解
Jul 27 Python
python实现多层感知器MLP(基于双月数据集)
Jan 18 Python
在Django下测试与调试REST API的方法详解
Aug 29 Python
pytorch 图像预处理之减去均值,除以方差的实例
Jan 02 Python
Python如何使用OS模块调用cmd
Feb 27 Python
全网首秀之Pycharm十大实用技巧(推荐)
Apr 27 Python
python如何随机生成高强度密码
Aug 19 Python
Python中用xlwt制作表格实例讲解
Nov 05 Python
详解Selenium-webdriver绕开反爬虫机制的4种方法
Oct 28 #Python
详解Python流程控制语句
Oct 28 #Python
详解selenium + chromedriver 被反爬的解决方法
Oct 28 #Python
手把手教你从PyCharm安装到激活(最新激活码),亲测有效可激活至2089年
Nov 25 #Python
Python字典实现伪切片功能
Oct 28 #Python
python使用selenium爬虫知乎的方法示例
Oct 28 #Python
怎么解决pycharm license Acti的方法
Oct 28 #Python
You might like
php学习笔记(三)操作符与控制结构
2011/08/06 PHP
解析php函数method_exists()与is_callable()的区别
2013/06/21 PHP
php正则取img标记中任意属性(正则替换去掉或改变图片img标记中的任意属性)
2013/08/13 PHP
ThinkPHP之R方法实例详解
2014/06/20 PHP
PhpStorm 2020.3:新增开箱即用的PHP 8属性(推荐)
2020/10/30 PHP
Microsfot .NET Framework4.0框架 安装失败的解决方法
2013/08/14 Javascript
jquery的trigger和triggerHandler的区别示例介绍
2014/04/20 Javascript
JavaScript仿商城实现图片广告轮播实例代码
2016/02/06 Javascript
JavaScript正则表达式匹配 div  style标签
2016/03/15 Javascript
基于javascript实现全屏漂浮广告
2016/03/31 Javascript
jQuery实现右键菜单、遮罩等效果代码
2016/09/27 Javascript
Angular.js中ng-if、ng-show和ng-hide的区别介绍
2017/01/20 Javascript
Ajax跨域实现代码(后台jsp)
2017/01/21 Javascript
微信小程序实现人脸检测功能
2018/05/25 Javascript
JavaScript反射与依赖注入实例详解
2018/05/29 Javascript
vue2.0 使用element-ui里的upload组件实现图片预览效果方法
2018/09/04 Javascript
python通过自定义isnumber函数判断字符串是否为数字的方法
2015/04/23 Python
python 简单的多线程链接实现代码
2016/08/28 Python
python GUI库图形界面开发之PyQt5结合Qt Designer创建信号与槽的详细方法与实例
2020/03/08 Python
Django自定义YamlField实现过程解析
2020/11/11 Python
HTML5打开手机扫码功能及优缺点
2017/11/27 HTML / CSS
华为俄罗斯官方网上商城:购买Huawei手机和平板
2017/04/21 全球购物
美国购买当代和现代家具网站:MODTEMPO
2018/07/20 全球购物
耐克奥地利官网:Nike奥地利
2019/08/16 全球购物
在阿联酋购买翻新手机和平板电脑:Teckzu
2021/02/12 全球购物
学校大课间活动方案
2014/01/30 职场文书
房地产开盘策划方案
2014/02/10 职场文书
高校教师岗位职责
2014/03/18 职场文书
小学教师师德师风承诺书
2015/04/28 职场文书
酒店员工手册范本
2015/05/14 职场文书
蜗居观后感
2015/06/11 职场文书
新郎父亲婚礼致辞
2015/07/27 职场文书
2015年小学远程教育工作总结
2015/07/28 职场文书
团队执行力培训心得体会
2015/08/15 职场文书
2019年销售人员的职业生涯规划书
2019/03/25 职场文书
Python中的协程(Coroutine)操作模块(greenlet、gevent)
2022/05/30 Python