有时我们可能需要编写一个完整的模块库,比如python对XML的处理就需要一堆的函数.这时候可能划分成多个文件,更加方便管理. 逻辑上也更加清晰. 因此python引入了对多文件模块包的支持.说白了,就是import的不是一个文件的内容,而是一个文件夹的内容.
看下面的示例:
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__']
>>> import xml
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'xml']
>>> import xml.sax.xmlreader
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'xml']
>>> dir(xml)
['_MINIMUM_XMLPLUS_VERSION', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'sax']
>>> dir(xml.sax)
['ContentHandler', 'ErrorHandler', 'InputSource', 'SAXException', 'SAXNotRecognizedException', 'SAXNotSupportedException',
'SAXParseException', 'SAXReaderNotAvailable', '__builtins__', '__doc__', '__file__', '__name__',
'__package__', '__path__', '_create_parser', '_exceptions', '_false', '_key', 'default_parser_list', 'handler',
'make_parser', 'parse', 'parseString', 'xmlreader']
>>> from xml import *
>>> dir(xml)
['_MINIMUM_XMLPLUS_VERSION', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'dom', 'etree', 'parsers', 'sax']
表面上看起来,和内容在单个文件内的import机制差不多. 我们可以到xml对应的目录下看看:
erlv@erlv-debian:/usr/lib/python2.7/xml$ ls *
__init__.py __init__.pyc __init__.pyo
dom:
domreg.py expatbuilder.py __init__.py minicompat.py minidom.py NodeFilter.py pulldom.py xmlbuilder.py
etree:
cElementTree.py ElementInclude.py ElementPath.py ElementTree.py __init__.py
parsers:
expat.py __init__.py
sax:
_exceptions.py expatreader.py handler.py __init__.py saxutils.py xmlreader.py
我们import的xmlreader,它的路径是xml/sax/xmlreader.py,和import xml.sax.xmlreader相同. 这实际上也正是python解释器实际的动作.
注意到,每个文件夹下都有一个_init__.py文件.这个是模块包中的必须文件,它帮助python解释器将该目录识别成包. 没有此文件的文件夹,python解释器不会把它当模块包文件夹的. _init__.py中一般会指定包中所有的模块,以及import此包时,需要预先import哪些包等初始化信息.当然,你可以往里面添加其他代码. 该脚本会在import 包时执行. 默认可以为空.
另外,还注意到有.py,.pyc和.pyo三个文件.
.py文件:Python源程序文件,文本文件
.pyc文件:编译成字节码的python文件,可以使用python解释器,或者调用pycompile模块生成该文件.
.pyo文件:进行一定编译优化的后的字节码文件.
另外,还可以控制python解释器,去掉”docstrings”,即代码中的无关文档字符串.