浅谈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中将单词首字母大写的capitalize()方法
May 18 Python
python中set常用操作汇总
Jun 30 Python
如何在python中使用selenium的示例
Dec 26 Python
tensorflow输出权重值和偏差的方法
Feb 10 Python
Python 生成 -1~1 之间的随机数矩阵方法
Aug 04 Python
python 判断矩阵中每行非零个数的方法
Jan 26 Python
Python Django框架模板渲染功能示例
Nov 08 Python
Java Spring项目国际化(i18n)详细方法与实例
Mar 20 Python
详解用Pytest+Allure生成漂亮的HTML图形化测试报告
Mar 31 Python
python suds访问webservice服务实现
Jun 26 Python
python爬取2021猫眼票房字体加密实例
Feb 19 Python
Python爬虫+tkinter界面实现历史天气查询的思路详解
Feb 22 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
关于zend studio 出现乱码问题的总结
2013/06/23 PHP
为PHP安装imagick时出现Cannot locate header file MagickWand.h错误的解决方法
2014/11/03 PHP
php.ini中的request_order推荐设置
2015/05/10 PHP
win10环境PHP 7 安装配置【教程】
2016/05/09 PHP
php metaphone()函数及php localeconv() 函数实例解析
2016/05/15 PHP
PHP机器学习库php-ml的简单测试和使用方法
2017/07/14 PHP
PHP依赖注入原理与用法分析
2018/08/21 PHP
TP5多入口设置实例讲解
2020/12/15 PHP
TNC vs BOOM BO3 第三场2.13
2021/03/10 DOTA
js控制表单不能输入空格的小例子
2013/11/20 Javascript
jquery插件jTimer(jquery定时器)使用方法
2013/12/23 Javascript
Angularjs中使用Filters详解
2016/03/11 Javascript
jQuery实现的表头固定效果实例【附完整demo源码下载】
2016/08/01 Javascript
Asp.Net之JS生成分页条的方法
2016/11/23 Javascript
nodejs使用express获取get和post传值及session验证的方法
2017/11/09 NodeJs
vue结合axios与后端进行ajax交互的方法
2018/07/06 Javascript
使用webpack打包后的vue项目如何正确运行(express)
2018/10/26 Javascript
react基本安装与测试示例
2020/04/27 Javascript
简单说明Python中的装饰器的用法
2015/04/24 Python
numpy中矩阵合并的实例
2018/06/15 Python
APIStar:一个专为Python3设计的API框架
2018/09/26 Python
python3爬虫学习之数据存储txt的案例详解
2019/04/24 Python
python实现图片九宫格分割
2021/03/07 Python
Python3 中作为一等对象的函数解析
2019/12/11 Python
Python操作Excel把数据分给sheet
2020/05/20 Python
PIL.Image.open和cv2.imread的比较与相互转换的方法
2020/06/03 Python
python Tornado框架的使用示例
2020/10/19 Python
CSS3实现的文本3D效果附图
2014/09/03 HTML / CSS
美国环保婴儿用品公司:The Honest Company
2017/11/23 全球购物
法国房车租赁网站:Yescapa
2019/08/26 全球购物
五一家具促销方案
2014/01/10 职场文书
护士长竞聘演讲稿
2014/04/30 职场文书
人力资源管理毕业求职信
2014/08/05 职场文书
党员贯彻十八大精神思想汇报范文
2014/10/25 职场文书
幼儿园庆六一主持词
2015/06/30 职场文书
vue+echarts实现多条折线图
2022/03/21 Vue.js