python3之工程中必须依赖的__init__.py
1. __init__.py
1.1 什么是__init__.py
在Python3工程里,当python3检测到一个目录下存在__init__.py文件时,Python3就会把它当成一个模块(module)。__init__.py可以是一个空文件,也可以有内容。
1.2 为什么需要__init__.py
使用Python3模块常见的情况是,在使用A.py时,需要import B.py,需要先拷贝到当前目录,然后再import,这样的做法在程序量较小的情况下是可行的,如果程序交互复杂程度稍高,就会复杂费力。有一种解决方法可以将多个.py文件组织起来,方便在外部统一调用以及在内部互相调用。
Python3中的__init__.py在包调用中起到了重要的作用。首先要明确Python3在执行import包的时候,执行的操作,按照Python3的文档描述,操作如下:
- 创建一个新的module对象(它可能包含多个module);
- 把这个module对象插入sys.module中;
- 装载module的代码(首先需要找到module程序所在的位置,其原理为:如果需要导入的module的名字是m1,则解释器必须找到m1.py,它首先在当前目录查找,然后是在环境变量PYTHONPATH中查找)
- 执行新的module中对应的代码。
一个简单的package示例如图所示。
其中__init__.py为空,解释器对其视作一个package处理。
第一层:pack1, pack2, main.py
第二层:pack1: __init__.py,module_A.py
pack2:__init__.py,module_B.py

当main.py调用脚本from pack1 import Module_A,由于from操作,会默认目录下存在pack1包,解释器会首先寻找__init__.py。也就是说,package内module的import是受__init__.py限制的。
2. Python3.3+的__init__.py
Python 3.3+版本以后,Python3具有隐式命名空间包,允许它创建不带__init__.py文件的包,允许隐式名称空间包意味着可以完全放弃提供__init__.py文件的要求,并使其不受到影响。所以这就是在Python3.3以后的版本中,有时候工程中忘记加入了__init__.py文件而工程仍然能够正常运行的原因。
3. Python3中的PYTHONPATH
PYTHONPATH是Python3中一个重要的环境变量,用于在导入模块的时候搜索路径。因为PYTHONPATH是Python3的搜索路径,所以默认我们import的模块都会从PYTHONPATH里面进行寻找。如果我们使用PYTHONPATH中的modules,那么在运行python3前,就要把path加到os.environ['PYTHONPATH'],如果在运行python3后再加,那些模块不能直接被导入。


可以看到,路径列表的第一个元素为相对路径下的当前目录。由于在导入模块的时候,解释器会按照列表的顺序搜索,直到找到第一个模块,所以优先导入的模块为同一目录下的模块。导入模块时搜索路径的顺序也可以改变,分两种情况:
- 通过sys.path.append(),sys.path.insert()等方法来改变,这种方法当重新启动解释器的时候,原来的设置会失效。
- 改变PYTHONPATH,这种设置方法永久有效。在这种情况下,可以通过在sys.path列表显示的路径中添加.pth文件来实现。
4. 若要通过setup.py打包工程时,需要依赖__init__.py
在Python3的PYTHONPATH中,包含Python3安装目录相关的一组路径(内置模块和标准库,以及其它第三方模块的共享路径),但是它不支持项目所在根目录这种形式,而是只支持文件所在目录的相对路径。以1.2小节中的示例,项目的根路径为D:\pytest_init,其中包含pack1(Module_A)和pack2(Module_B)包。项目根路径D:\pytest_init是需要放在PYTHONPATH中的,这样python解释器才可以通过包名互相访问。
而setup.py所做的主要事情:将整个项目添加到PYTHONPATH中,setup.py中所记录的就是项目模块添加到PYTHONPATH的规则。setup.py中会定义此项目中有哪些模块需要被加入到PYTHONPATH,在这个过程中可以把测试项目过滤掉,而对项目中的模块进行打包时,setup.py会默认该模块包含并优先加载其中的__init__.py文件,因此在所要加入的每个模块中,都必须要有__init__.py文件的存在以保证所有需要导入的包都能够正确被找到并被导入。即,在使用setup.py打包的项目中,__init__.py必须包含在每个模块包的目录中,以便自动找到软件包,这样打包的软件包仅在包含__init__.py文件的情况下才能被识别。setup.py中还会定义需要的第三方依赖包,使用安装命令可以同时安装这些第三方依赖包等等。
python3之工程中必须依赖的__init__.py的更多相关文章
- 在Xcode5和Android Studio添加工程间的依赖
正在编辑中,尚未完成 先看看ios的target是什么,请先参看http://www.cocoachina.com/bbs/read.php?tid-10884.html做个大概了解 这里有一篇文章, ...
- Python自定义Module中__init__.py文件介绍
./pyModuleTest/├── addutil│ ├── add.py│ ├── add.pyc│ ├── __init__.py│ ├── __init__.pyc│ └─ ...
- 转载:【学习之家】Python中__init__.py文件的作用
Python中__init__.py文件的作用详解 Python中__init__.py文件的作用详解 来源:学习之家 作者:xuexi110 人气:357 发布时间:2016-09-29 摘要:__ ...
- python 中的__init__.py的用法与个人理解
使用Python模块常见的情况是,事先写好A.py文件,需要import B.py文件时,先拷贝到当前目录,然后再import 这样的做法在程序量较小的情况下是可行的,如果程序交互复杂程度稍高,就很费 ...
- Python __init__.py 作用详解
__init__.py 文件的作用是将文件夹变为一个Python模块,Python 中的每个模块的包中,都有__init__.py 文件. 通常__init__.py 文件为空,但是我们还可以为它增加 ...
- Python __init__.py 文件使用
__init__.py的主要作用是: 1. Python中package的标识,不能删除 2. 定义__all__用来模糊导入 3. 编写Python代码(不建议在__init__中写python模块 ...
- Python学习笔记之__init__.py文件的作用
参考地址:http://www.cnblogs.com/Lands-ljk/p/5880483.html Python __init__.py 作用详解 __init__.py 文件的作用是将文件夹变 ...
- 初学者:__init__.py文件的作用
__init__.py 文件的作用及意义 __init__.py文件是一个包必须的文件,即使它是空的,但也是必须的,如果没有这个文件,python将不会把该文件夹当做一个package,而仅仅是一个d ...
- python3 module中__init__.py的需要注意的地方
网上关于__init__.py的作用的资料到处都是,我在此就不再啰嗦哪些了. 若有需要.请各位看官去搜搜即可. 最近刚开始用Python3 就遇到了这个比较有意思的事情 闲言少叙,下面要介绍的是pyt ...
随机推荐
- mfc HackerTools监控键盘按键
string GetKey(int Key) { string KeyString = ""; //判断符号输入 const int KeyPressMask = 0x800000 ...
- CentOS_Server with GUI入门
安装模式: Server with GUI:基本的桌面系统,包括常用的桌面软件,如文档查看工具 Minimal:基本的系统,不含有任何可选的软件包 Basic Server :安装的基本系统的平台支持 ...
- indexedDB数据库完整创建流程
1.打开数据库 使用 IndexedDB 的第一步是打开数据库,使用indexedDB.open()方法 var request = window.indexedDB.open(databaseNam ...
- 取消Ubuntu开机硬盘自检
修改/etc/fstab文件,最后一列全改为0,测试能正常启动,尚未出现再次自检的情况 sudo gedit /etc/fstab
- 100个裁判对n个选手做无并列排名问题探析
原题:n 个选手(n ≥ 3)参加花样自行车比赛,100 个裁判独立对各选手的表现给出无并列排名.已知对任意三个选手 A.B.C 和任意三个裁判 X.Y.Z 均不会出现如下的情形:X 给出 A > ...
- 一个double free相关问题的澄清
引言 前一阵定位 Oracle 的 OCI 接口相关的一个内存释放问题,在网上看到了链接如下的这篇文章: 一个C++bug引入的许多知识 看到后面说 vector 里的两个单元里的内部成员指针地址是一 ...
- MutationObserver API
1.概述 MutationObserver接口提供了监视对DOM树所做更改的能力.它被设计为旧的Mutation Events功能的替代品,该功能是DOM3 Events规范的一部分. 但是,它与Mu ...
- SpringBoot详解(一)——
https://www.cnblogs.com/lifullmoon/p/14957771.html https://www.cnblogs.com/lifullmoon/p/14957751.htm ...
- 各种插值法的python实现
一维插值 插值不同于拟合.插值函数经过样本点,拟合函数一般基于最小二乘法尽量靠近所有样本点穿过.常见插值方法有拉格朗日插值法.分段插值法.样条插值法. 拉格朗日插值多项式:当节点数n较大时,拉格朗日插 ...
- [考试总结]noip模拟47
感觉自己放弃题目还是过于容易. 其实第一题不是很难,但是自己拿了一个暴力就走人了.. 然后其实简单优化一下子就有不少分数. 然后第二题的本质不同的子序列个数的方程没有推出来,如果推出来就会直接有 \( ...