一、什么是模块
如果你从Python解释器退出并再次进入,之前的定义(函数和变量)都会丢失。因此,如果你想编写一个稍长些的程序,最好使用文本编辑器为解释器准备输入并将该文件作为输入运行。这被称作编写 脚本 。随着程序变得越来越长,你或许会想把它拆分成几个文件,以方便维护。你亦或想在不同的程序中使用一个便捷的函数, 而不必把这个函数复制到每一个程序中去。
为支持这些,Python有一种方法可以把定义放在一个文件里,并在脚本或解释器的交互式实例中使用它们。这样的文件被称作 模块 ;模块中的定义可以 导入 到其它模块或者 主模块(你在顶级和计算器模式下执行的脚本中可以访问的变量集合)
模块是一个包含Python定义和语句的文件。文件名就是模块名后跟文件后缀 .py
。在一个模块内部,模块名(作为一个字符串)可以通过全局变量 __name__
的值获得
二、模块编写与使用
使用文本编辑器在当前目录下创建一个名为 fibo.py
的文件, 键入以下代码
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
def fib2(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a+b
return result
使用模块中的函数
现在进入Python解释器,并用以下命令导入该模块:
>>> import fibo
在当前的符号表中,这并不会直接进入到定义在 fibo
函数内的名称;它只是进入到模块名 fibo
中。你可以用模块名访问这些函数
>>> fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name___
'fibo'
如果你想经常使用某个函数,你可以把它赋值给一个局部变量
>>> fib = fibo.fib
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
三、模块导入方法
import 模块名
from 模块名 import 模块中的属性
>>> from fibo import fib, fib2
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
import 模块名 as 新模块名
>>> import fibo as fib
>>> fib.fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
from 模块名 import 模块中的属性 as 新属性名
>>> from fibo import fib as fibonacci
>>> fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
注意:
- 出于效率的考虑,每个模块在每个解释器会话中只被导入一次。
- 因此,如果你更改了你的模块,则必须重新启动解释器, 或者,如果它只是一个要交互式地测试的模块,请使用
importlib.reload()
,例如import importlib; importlib.reload(modulename)
四、脚本方式执行模块
模块里的代码会被执行,就好像你导入了模块一样,但是 __name__
被赋值为 "__main__"
。 这意味着通过在你的模块末尾添加这些代码
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
- 如果模块是被导入的,这些代码是不运行的
五、模块搜索路径
- 当一个名为
spam
的模块被导入的时候,解释器首先寻找具有该名称的内置模块 - 如果没有找到,然后解释器从
sys.path
变量给出的目录列表里寻找名为spam.py
的文件
sys.path包含的路径
- 包含输入脚本的目录(或者未指定文件时的当前目录)
PYTHONPATH
(一个包含目录名称的列表,它和shell
变量PATH
有一样的语法)- 取决于安装的默认设置
六、编译过的python模块
为了加速模块载入,Python在 __pycache__
目录里缓存了每个模块的编译后版本,名称为 module.version.pyc
,其中名称中的版本字段对编译文件的格式进行编码; 它一般使用Python版本号。例如,在CPython版本3.3中,spam.py
的编译版本将被缓存为 __pycache__/spam.cpython-33.pyc
。此命名约定允许来自不同发行版和不同版本的Python的已编译模块共存。
Python根据编译版本检查源的修改日期,以查看它是否已过期并需要重新编译。这是一个完全自动化的过程。此外,编译的模块与平台无关,因此可以在具有不同体系结构的系统之间共享相同的库。
Python在两种情况下不会检查缓存。首先,对于从命令行直接载入的模块,它从来都是重新编译并且不存储编译结果;其次,如果没有源模块,它不会检查缓存。为了支持无源文件(仅编译)发行版本, 编译模块必须是在源目录下,并且绝对不能有源模块。
七、包
包是一种通过用“带点号的模块名”来构造 Python 模块命名空间的方法。 例如,模块名 A.B
表示 A
包中名为 B
的子模块
例如, 处理声音包
sound/ Top-level package
__init__.py Initialize the sound package
formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
...
filters/ Subpackage for filters
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
当导入这个包时,Python搜索 sys.path 里的目录,查找包的子目录
必须要有 __init__.py
文件才能让 Python 将包含该文件的目录当作包。 这样可以防止具有通常名称例如 string 的目录在无意中隐藏稍后在模块搜索路径上出现的有效模块。 在最简单的情况下,__init__.py
可以只是一个空文件,但它也可以执行包的初始化代码或设置 __all__
变量
7.1 包的导入
- 导入包的单个模块
import sound.effects.echo
- 这会加载子模块 sound.effects.echo 。但引用它时必须使用它的全名
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
- 导入包的子模块
from sound.effects import echo
- 直接导入所需的函数或变量
from sound.effects.echo import echofilter
当使用 from package import item
时,item
可以是包的子模块(或子包),也可以是包中定义的其他名称,如函数,类或变量
-
form package import *
: 会导入包__init__.py
中的__all__
列表变量包含的所有模块 -
相对路径导入
from . import echo
from .. import formats
from ..filters import equalizer
- 请注意,相对导入是基于当前模块的名称进行导入的。由于主模块的名称总是 "main" ,因此用作Python应用程序主模块的模块必须始终使用绝对导入。