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的文档描述,操作如下:

  1. 创建一个新的module对象(它可能包含多个module);
  2. 把这个module对象插入sys.module中;
  3. 装载module的代码(首先需要找到module程序所在的位置,其原理为:如果需要导入的module的名字是m1,则解释器必须找到m1.py,它首先在当前目录查找,然后是在环境变量PYTHONPATH中查找)
  4. 执行新的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后再加,那些模块不能直接被导入。

  可以看到,路径列表的第一个元素为相对路径下的当前目录。由于在导入模块的时候,解释器会按照列表的顺序搜索,直到找到第一个模块,所以优先导入的模块为同一目录下的模块。导入模块时搜索路径的顺序也可以改变,分两种情况:

  1. 通过sys.path.append(),sys.path.insert()等方法来改变,这种方法当重新启动解释器的时候,原来的设置会失效。
  2. 改变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的更多相关文章

  1. 在Xcode5和Android Studio添加工程间的依赖

    正在编辑中,尚未完成 先看看ios的target是什么,请先参看http://www.cocoachina.com/bbs/read.php?tid-10884.html做个大概了解 这里有一篇文章, ...

  2. Python自定义Module中__init__.py文件介绍

    ./pyModuleTest/├── addutil│   ├── add.py│   ├── add.pyc│   ├── __init__.py│   ├── __init__.pyc│   └─ ...

  3. 转载:【学习之家】Python中__init__.py文件的作用

    Python中__init__.py文件的作用详解 Python中__init__.py文件的作用详解 来源:学习之家 作者:xuexi110 人气:357 发布时间:2016-09-29 摘要:__ ...

  4. python 中的__init__.py的用法与个人理解

    使用Python模块常见的情况是,事先写好A.py文件,需要import B.py文件时,先拷贝到当前目录,然后再import 这样的做法在程序量较小的情况下是可行的,如果程序交互复杂程度稍高,就很费 ...

  5. Python __init__.py 作用详解

    __init__.py 文件的作用是将文件夹变为一个Python模块,Python 中的每个模块的包中,都有__init__.py 文件. 通常__init__.py 文件为空,但是我们还可以为它增加 ...

  6. Python __init__.py 文件使用

    __init__.py的主要作用是: 1. Python中package的标识,不能删除 2. 定义__all__用来模糊导入 3. 编写Python代码(不建议在__init__中写python模块 ...

  7. Python学习笔记之__init__.py文件的作用

    参考地址:http://www.cnblogs.com/Lands-ljk/p/5880483.html Python __init__.py 作用详解 __init__.py 文件的作用是将文件夹变 ...

  8. 初学者:__init__.py文件的作用

    __init__.py 文件的作用及意义 __init__.py文件是一个包必须的文件,即使它是空的,但也是必须的,如果没有这个文件,python将不会把该文件夹当做一个package,而仅仅是一个d ...

  9. python3 module中__init__.py的需要注意的地方

    网上关于__init__.py的作用的资料到处都是,我在此就不再啰嗦哪些了. 若有需要.请各位看官去搜搜即可. 最近刚开始用Python3 就遇到了这个比较有意思的事情 闲言少叙,下面要介绍的是pyt ...

随机推荐

  1. log4j.properties配置文件及详解

    log4j配置文件有三个主要的组件:Logger,Appender和Layout,分别为日志类型,日志输出目的地,日志输出格式. 1. 配置日志级别及appenderName log4j.rootLo ...

  2. 08.SpringMVC之方法返回值

    返回ModelAndView Controller类方法中定义ModelAndView对象并返回,对象中可添加model数据.指定view.之前我就已讲过,在此并不过多赘述. 返回void 在Cont ...

  3. apche的BeanUtils避免使用!

    原文出处 建议,不要使用apache的BeanUtils进行属性拷贝了,建议使用Spring 核心包bean下面的BeanUtils进行替代! 使用和对比出处

  4. Jsoup学习笔记

    时间:2016-7-7 00:05 jsoup 是一款 Java 的HTML 解析器,可直接解析某个URL地址.HTML文本内容.它提供了一套非常省力的API,可通过DOM,CSS以及类似于JQuer ...

  5. Linux下MySQL主从复制(GTID)+读写分离(ProxySQL)-实施笔记

    GTID概念: GTID( Global Transaction Identifier)全局事务标识.GTID 是 5.6 版本引入的一个有关于主从复制的重大改进,相对于之前版本基于 Binlog 文 ...

  6. for循环操作(for...in、forEach)

    1.for...in语句用于对数组或者对象的属性进行循环操作,是for循环的一种. 注意:该方法可用于数组或对象. 语法:  for(变量 in 对象/数组){} 如: var obj = { nam ...

  7. Ubuntu在桌面壁纸上显示计算机名

    时间:2018-07-16 记录:byzqy 介绍: 在管理多台计算机时,将每台计算机的ID或者计算机名醒目的显示在电脑桌面,往往是一个不错的选择.下面记录一下在Ubuntu 16.04上使用Pyth ...

  8. 用C++实现的增强Euler筛法程序

    运行示例 PS H:\Read\num\x64\Release> .\eulerSievePro EulerSievePro: a method to find out all primes b ...

  9. Mybatis笔记(1)

    一.Mabits简介 1.1 原始JDBC的分析 问题 ①数据库连接创建.释放频繁造成系统资源浪费从而影响系统性能 ②sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大,s ...

  10. Ajax技术---核心XMLHttpRequest对象

    Ajax 的全称是Asynchronous JavaScript and XML,其中,Asynchronous 是异步的意思,它有别于传统web开发中采用的同步的方式. (一)ajax技术的意义 我 ...