Python 包
以下为简述。详见python cookbook 模块与包
包,包含一组模块和__init__.py
的文件夹。
这项技术有助于解决不同应用程序中使用的模块名称之间命名空间冲突的问题。包是通过使用与其相同的名称创建目录,并在该目录中创建__init__.py
。如果需要,可以向该目录中放入其他源文件、编译后的扩展和子包。
按如下方式组织一个包
只要第一次导入包中的任何部分,就会执行相应的__init__.py
中的代码。这个文件可以为空,也可以包含可执行代码。在import语句执行期间,遇到的所有__init__.py
都会执行。如import packet.A.a
,先执行packet目录下的__init__.py
,然后执行A目录下的__init__.py
。
在使用包时,如果导入的是模块名,则需要注意,
导入的是包中的模块,正常使用即可。如
packet/__init__.py
与packet/A/__init__.py
均为空from packet.A import a #正常,使用a中的属性,a.attr即可
import packet.A.a as a #正常,使用a.attr即可
from packet.A.a import * #正常,直接使用a中的属性attr即可
导入的是包,则需要修改
__init__.py
,__init__.py不能为空
。使用该语句时,通常希望将某个包中的所有子模块导入当前命名空间中。但是,由于各个操作系统之间的文件名约定不同(尤其是区分大小写上),Python无法准确地确定各个模块的具体内容。所以,导入包时只会导入与包同路径下的
__init__.py
中的内容。可利用__all__
。测试如下
packet/__init__.py
为空时,如import packet packet.d.attr #AttributeError: 'module' object has no attribute 'd' packet.A.a.attr #AttributeError: 'module' object has no attribute 'A'
from packet import A print A.a.attr #AttributeError: 'module' object has no attribute 'a'
修改
packet/__init__.py
,,内容如下(此时packet/A/__init__.py
仍为空)import d import A
import packet packet.d.attr #正常 packet.A.a.attr #AttributeError: 'module' object has no attribute 'a',找到了包A但是找不到模块a.py
from packet import A print A.a.attr #AttributeError: 'module' object has no attribute 'a'
继续修改
packet/A/__init__.py
,内容如下import a
import packet packet.d.attr #正常 packet.A.a.attr #正常
from packet import A print A.a.attr #正常
相对导入
如果包中的模块想要使用同一个包中的模块,如packet/A/a.py想要导入packet/d.py或者packet/B/d.py
。为此,需要完全限定名称(如packet.B.d,绝对路径导入)或使用包的相对导入,如
packet/A/a.py导入packet/A/d.py ,packet/A/a.py内容如下
相对导入
from . import d #.代表当前路径
绝对导入
import packet.A.d as d
packet/A/a.py导入packet/d.py,packet/A/a.py内容如下
相对导入
from .. import d #..代表上一层路径
绝对导入
import packet.d as d
packet/A/a.py导入packet/B/d.py,packet/A/a.py内容如下
相对导入
from ..B import d #..B代表上层路径中的B
绝对导入
import packet.B.d as d
在包中,要避免使用import module来导入包的子模块,在早期的Python版本中,无法确定import module语句引用的是标准库模块还是包的子模块。相对导入和绝对导入能更加清楚的表明导入意图。
使用相对导入的注意事项,
相对导入只能使用from module import attr形式的导入语句,import ..B.d这样的语法是不对的;
相对导入只能在包中使用,不能在用户的应用程序中使用相对导入,
因为不论是相对导入还是绝对导入,都是相当于当前模块来说的,对于用户的主应用程序,也就是入口文件,模块名总是为
__main__
, 所以用户的应用程序必须使用绝对导入。package中可以使用相对导入和绝对导入;使用相对路径import 的Python脚本不能直接运行,要保证这个模块不是入口文件,只有作为被导入的模块才可以使用相对导入。原因正如手册中描述的,所谓相对路径其实就是相对于当前module的路径,如果直接执行脚本,这个module的name就是
__main__
, 而不是module原来的name, 这样相对路径也就不是原来的相对路径了,导入就会失败,出现错误“ValueError: Attempted relative import in non-package” ;
转载请标明出处,原文地址(http://blog.csdn.net/lis_12/article/details/53966799).
如果觉得本文对您有帮助,请点击‘顶’支持一下,您的支持是我写作最大的动力,谢谢。
参考网址: