Python 标准库
- 多媒体服务
audioop
—- 处理原始音频数据aifc
—- 读写 AIFF 和 AIFC 文件sunau
—- 读写 Sun AU 文件wave
—- 读写WAV格式文件chunk
—- 读取 IFF 分块数据colorsys
—- 颜色系统间的转换imghdr
—- 推测图像类型sndhdr
—- 推测声音文件的类型ossaudiodev
—- 访问兼容OSS的音频设备
- 国际化
gettext
—- 多语种国际化服务locale
—- 国际化服务
- 程序框架
turtle
—- 海龟绘图cmd
—- 支持面向行的命令解释器shlex
—— 简单的词法分析
- Tk图形用户界面(GUI)
tkinter
—- Tcl/Tk的Python接口tkinter.colorchooser
—- 颜色选择对话框tkinter.font
—- Tkinter 字体封装- Tkinter 对话框
tkinter.messagebox
—- Tkinter 消息提示tkinter.scrolledtext
—- 滚动文字控件tkinter.dnd
—- 拖放操作支持tkinter.ttk
—- Tk主题部件tkinter.tix
—- TK扩展包- IDLE
- 开发工具
typing
—- 类型提示支持pydoc
—- 文档生成器和在线帮助系统- Python Development Mode
- Effects of the Python Development Mode
- ResourceWarning Example
- Bad file descriptor error example
doctest
—- 测试交互性的Python示例unittest
—- 单元测试框架unittest.mock
—- 模拟对象库unittest.mock
上手指南- 2to3 - 自动将 Python 2 代码转为 Python 3 代码
test
—- Python回归测试包test.support
—- Utilities for the Python test suitetest.support.socket_helper
—- Utilities for socket teststest.support.script_helper
—- Utilities for the Python execution teststest.support.bytecode_helper
—- Support tools for testing correct bytecode generationtest.support.threading_helper
—- Utilities for threading teststest.support.os_helper
—- Utilities for os teststest.support.import_helper
—- Utilities for import teststest.support.warnings_helper
—- Utilities for warnings tests
- 调试和分析
- 审计事件表
bdb
—- Debugger frameworkfaulthandler
—- Dump the Python tracebackpdb
—- Python 的调试器- Python Profilers 分析器
timeit
—- 测量小代码片段的执行时间trace
—- 跟踪Python语句的执行tracemalloc
—- 跟踪内存分配
- 软件打包和分发
distutils
—- 构建和安装 Python 模块ensurepip
—- Bootstrapping thepip
installervenv
—- 创建虚拟环境zipapp
—- Manage executable Python zip archives
- Python运行时服务
sys
—- 系统相关的参数和函数sysconfig
—- Provide access to Python’s configuration informationbuiltins
—- 内建对象__main__
—- Top-level code environmentwarnings
—— 警告信息的控制dataclasses
—- 数据类contextlib
—- 为with
语句上下文提供的工具abc
—- 抽象基类atexit
—- 退出处理器traceback
—- 打印或检索堆栈回溯__future__
—- Future 语句定义gc
—- 垃圾回收器接口inspect
—- 检查对象site
—— 指定域的配置钩子
- 自定义 Python 解释器
code
—- 解释器基类codeop
—- 编译Python代码
- 导入模块
zipimport
—- 从 Zip 存档中导入模块pkgutil
—- 包扩展工具modulefinder
—- 查找脚本使用的模块runpy
——查找并执行 Python 模块importlib
—-import
的实现- Using
importlib.metadata
- Python 语言服务
ast
—- 抽象语法树symtable
—- Access to the compiler’s symbol tablestoken
—- 与Python解析树一起使用的常量keyword
—- 检验Python关键字tokenize
—- 对 Python 代码使用的标记解析器tabnanny
—- 模糊缩进检测pyclbr
—- Python 模块浏览器支持py_compile
—- 编译 Python 源文件compileall
—- Byte-compile Python librariesdis
—- Python 字节码反汇编器pickletools
—- pickle 开发者工具集
- Windows系统相关模块
msilib
—- Read and write Microsoft Installer filesmsvcrt
—- 来自 MS VC++ 运行时的有用例程winreg
—- 访问 Windows 注册表winsound
—— Windows 系统的音频播放接口
- Unix 专有服务
posix
—- 最常见的 POSIX 系统调用pwd
—- 用户密码数据库spwd
—- The shadow password databasegrp
—- 组数据库crypt
—— 验证 Unix 口令的函数termios
—- POSIX 风格的 tty 控制tty
—- 终端控制功能pty
—- 伪终端工具fcntl
—— 系统调用fcntl
和ioctl
pipes
—- 终端管道接口resource
—- Resource usage informationnis
—- Sun 的 NIS (黄页) 接口- Unix syslog 库例程
- 被取代的模块
optparse
—- 解析器的命令行选项imp
—- Access the import internals
- 未创建文档的模块
- 平台特定模块
- Security Considerations
多媒体服务
本章描述的模块实现了主要用于多媒体应用的各种算法或接口。 它们可在安装时自行决定。 这是一个概述:
audioop
—- 处理原始音频数据aifc
—- 读写 AIFF 和 AIFC 文件sunau
—- 读写 Sun AU 文件- AU_read 对象
- AU_write 对象
wave
—- 读写WAV格式文件- Wave_read对象
- Wave_write 对象
chunk
—- 读取 IFF 分块数据colorsys
—- 颜色系统间的转换imghdr
—- 推测图像类型sndhdr
—- 推测声音文件的类型ossaudiodev
—- 访问兼容OSS的音频设备- Audio Device Objects
- Mixer Device Objects
audioop
—- 处理原始音频数据
audioop
模块包含针对声音片段的一些有用操作。它操作的声音片段由 8、16、24 或 32 位宽的有符号整型采样值组成,存储在 类字节串对象 中。除非特别说明,否则所有标量项目均为整数。
在 3.4 版更改: 增加了对 24 位采样的支持。现在,所有函数都接受任何 类字节串对象。而传入字符串会立即导致错误。
本模块提供对 a-LAW、u-LAW 和 Intel/DVI ADPCM 编码的支持。
部分更复杂的操作仅接受 16 位采样,而其他操作始终需要采样大小(以字节为单位)作为该操作的参数。
此模块定义了下列变量和函数:
exceptionaudioop.error
所有错误都会抛出此异常,比如采样值的字节数未知等等。
audioop.add
(fragment1, fragment2, width)
两个采样作为参数传入,返回一个片段,该片段是两个采样的和。width 是采样位宽(以字节为单位),可以取 1
, 2
, 3
或 4
。两个片段的长度应相同。如果发生溢出,较长的采样将被截断。
audioop.adpcm2lin
(adpcmfragment, width, state)
将 Intel/DVI ADPCM 编码的片段解码为线性片段。关于 ADPCM 编码的详情请参阅 lin2adpcm()
的描述。返回一个元组 (sample, newstate)
,其中 sample 的位宽由 width 指定。
audioop.alaw2lin
(fragment, width)
将 a-LAW 编码的声音片段转换为线性编码声音片段。由于 a-LAW 编码采样值始终为 8 位,因此这里的 width 仅指输出片段的采样位宽。
audioop.avg
(fragment, width)
返回片段中所有采样值的平均值。
audioop.avgpp
(fragment, width)
返回片段中所有采样值的平均峰峰值。由于没有进行过滤,因此该例程的实用性尚存疑。
audioop.bias
(fragment, width, bias)
返回一个片段,该片段由原始片段中的每个采样值加上偏差组成。在溢出时采样值会回卷 (wrap around)。
audioop.byteswap
(fragment, width)
“按字节交换”片段中的所有采样值,返回修改后的片段。将大端序采样转换为小端序采样,反之亦然。
3.4 新版功能.
audioop.cross
(fragment, width)
将片段作为参数传入,返回其中过零点的数量。
audioop.findfactor
(fragment, reference)
返回一个系数 F 使得 rms(add(fragment, mul(reference, -F)))
最小,即返回的系数乘以 reference 后与 fragment 最匹配。两个片段都应包含 2 字节宽的采样。
本例程所需的时间与 len(fragment)
成正比。
audioop.findfit
(fragment, reference)
尽可能尝试让 reference 匹配 fragment 的一部分(fragment 应较长)。从概念上讲,完成这些靠从 fragment 中取出切片,使用 findfactor()
计算最佳匹配,并最小化结果。两个片段都应包含 2 字节宽的采样。返回一个元组 (offset, factor)
,其中 offset 是在 fragment 中的偏移量(整数),表示从此处开始最佳匹配,而 factor 是由 findfactor()
定义的因数(浮点数)。
audioop.findmax
(fragment, length)
在 fragment 中搜索所有长度为 length 的采样切片(不是字节!)中,能量最大的那一个切片,即返回 i 使得 rms(fragment[i*2:(i+length)*2])
最大。两个片段都应包含 2 字节宽的采样。
本例程所需的时间与 len(fragment)
成正比。
audioop.getsample
(fragment, width, index)
返回片段中采样值索引 index 的值。
audioop.lin2adpcm
(fragment, width, state)
将采样转换为 4 位 Intel/DVI ADPCM 编码。ADPCM 编码是一种自适应编码方案,其中每个 4 比特数字是一个采样值与下一个采样值之间的差除以(不定的)步长。IMA 已选择使用 Intel/DVI ADPCM 算法,因此它很可能成为标准。
state 是一个表示编码器状态的元组。编码器返回一个元组 (adpcmfrag, newstate)
,而 newstate 要在下一次调用 lin2adpcm()
时传入。在初始调用中,可以将 None
作为 state 传递。adpcmfrag 是 ADPCM 编码的片段,每个字节打包了 2 个 4 比特值。
audioop.lin2alaw
(fragment, width)
将音频片段中的采样值转换为 a-LAW 编码,并将其作为字节对象返回。a-LAW 是一种音频编码格式,仅使用 8 位采样即可获得大约 13 位的动态范围。Sun 音频硬件等使用该编码。
audioop.lin2lin
(fragment, width, newwidth)
将采样在 1、2、3 和 4 字节格式之间转换。
注解
在某些音频格式(如 .WAV 文件)中,16、24 和 32 位采样是有符号的,但 8 位采样是无符号的。因此,当将这些格式转换为 8 位宽采样时,还需使结果加上 128:
new_frames = audioop.lin2lin(frames, old_width,1)
new_frames = audioop.bias(new_frames,1,128)
反之,将 8 位宽的采样转换为 16、24 或 32 位时,必须采用相同的处理。
audioop.lin2ulaw
(fragment, width)
将音频片段中的采样值转换为 u-LAW 编码,并将其作为字节对象返回。u-LAW 是一种音频编码格式,仅使用 8 位采样即可获得大约 14 位的动态范围。Sun 音频硬件等使用该编码。
audioop.max
(fragment, width)
返回片段中所有采样值的最大 绝对值。
audioop.maxpp
(fragment, width)
返回声音片段中的最大峰峰值。
audioop.minmax
(fragment, width)
返回声音片段中所有采样值的最小值和最大值组成的元组。
audioop.mul
(fragment, width, factor)
返回一个片段,该片段由原始片段中的每个采样值乘以浮点值 factor 组成。如果发生溢出,采样将被截断。
audioop.ratecv
(fragment, width, nchannels, inrate, outrate, state[, weightA[, weightB]])
转换输入片段的帧速率。
state 是一个表示转换器状态的元组。转换器返回一个元组 (newfragment, newstate)
,而 newstate 要在下一次调用 ratecv()
时传入。初始调用应传入 None
作为 state。
参数 weightA 和 weightB 是简单数字滤波器的参数,默认分别为 1
和 0
。
audioop.reverse
(fragment, width)
将片段中的采样值反转,返回修改后的片段。
audioop.rms
(fragment, width)
返回片段的均方根值,即 sqrt(sum(S_i^2)/n)
。
测量音频信号的能量。
audioop.tomono
(fragment, width, lfactor, rfactor)
将立体声片段转换为单声道片段。左通道乘以 lfactor,右通道乘以 rfactor,然后两个通道相加得到单声道信号。
audioop.tostereo
(fragment, width, lfactor, rfactor)
由单声道片段生成立体声片段。立体声片段中的两对采样都是从单声道计算而来的,即左声道是乘以 lfactor,右声道是乘以 rfactor。
audioop.ulaw2lin
(fragment, width)
将 u-LAW 编码的声音片段转换为线性编码声音片段。由于 u-LAW 编码采样值始终为 8 位,因此这里的 width 仅指输出片段的采样位宽。
请注意,诸如 mul()
或 max()
之类的操作在单声道和立体声间没有区别,即所有采样都作相同处理。如果出现问题,应先将立体声片段拆分为两个单声道片段,之后再重组。以下是如何进行该操作的示例:
def mul_stereo(sample, width, lfactor, rfactor):
lsample = audioop.tomono(sample, width,1,0)
rsample = audioop.tomono(sample, width,0,1)
lsample = audioop.mul(lsample, width, lfactor)
rsample = audioop.mul(rsample, width, rfactor)
lsample = audioop.tostereo(lsample, width,1,0)
rsample = audioop.tostereo(rsample, width,0,1)
return audioop.add(lsample, rsample, width)
如果使用 ADPCM 编码器构造网络数据包,并且希望协议是无状态的(即能够容忍数据包丢失),则不仅需要传输数据,还应该传输状态。请注意,必须将初始状态(传入 lin2adpcm()
的状态)发送给解码器,不能发送最终状态(编码器返回的状态)。如果要使用 struct.Struct
以二进制保存状态,可以将第一个元素(预测值)用 16 位编码,将第二个元素(增量索引)用 8 位编码。
本 ADPCM 编码器从不与其他 ADPCM 编码器对立,仅针对自身。本开发者可能会误读标准,这种情况下它们将无法与相应标准互操作。
乍看之下 find*()
例程可能有些可笑。它们主要是用于回声消除,一种快速有效的方法是选取输出样本中能量最高的片段,在输入样本中定位该片段,然后从输入样本中减去整个输出样本:
def echocancel(outputdata, inputdata):
pos = audioop.findmax(outputdata,800)# one tenth second
out_test = outputdata[pos*2:]
in_test = inputdata[pos*2:]
ipos, factor = audioop.findfit(in_test, out_test)
# Optional (for better cancellation):
# factor = audioop.findfactor(in_test[ipos*2:ipos*2+len(out_test)],
# out_test)
prefill ='\0'*(pos+ipos)*2
postfill ='\0'*(len(inputdata)-len(prefill)-len(outputdata))
outputdata = prefill + audioop.mul(outputdata,2,-factor)+ postfill
return audioop.add(inputdata, outputdata,2)
aifc
—- 读写 AIFF 和 AIFC 文件
源代码: Lib/aifc.py
本模块提供读写 AIFF 和 AIFF-C 文件的支持。AIFF 是音频交换文件格式 (Audio Interchange File Format),一种用于在文件中存储数字音频采样的格式。AIFF-C 是该格式的更新版本,其中包括压缩音频数据的功能。
音频文件内有许多参数,用于描述音频数据。采样率或帧率是每秒对声音采样的次数。通道数表示音频是单声道,双声道还是四声道。每个通道的每个帧包含一次采样。采样大小是以字节表示的每次采样的大小。因此,一帧由 nchannels * samplesize
(通道数采样大小)字节组成,而一秒钟的音频包含 nchannels * samplesize * framerate
(通道数采样大小*帧率)字节。
例如,CD 质量的音频采样大小为 2 字节(16位),使用 2 个声道(立体声),且帧速率为 44,100 帧/秒。这表示帧大小为 4 字节 (22),一秒钟占用 22*44100 字节(176,400 字节)。
aifc
模块定义了以下函数:
aifc.open
(file, mode=None)
打开一个 AIFF 或 AIFF-C 文件并返回一个对象实例,该实例具有下方描述的方法。参数 file 是文件名称字符串或 文件对象。当打开文件用于读取时,mode 必须为 'r'
或 'rb'
,当打开文件用于写入时,mode 必须为 'w'
或 'wb'
。如果该参数省略,则使用 file.mode
的值(如果有),否则使用 'rb'
。当文件用于写入时,文件对象应该支持 seek 操作,除非提前获知写入的采样总数,并使用 writeframesraw()
和 setnframes()
。open()
函数可以在 with
语句中使用。当 with
块执行完毕,将调用 close()
方法。
在 3.4 版更改: 添加了对 with
语句的支持。
当打开文件用于读取时,由 open()
返回的对象具有以下几种方法:
aifc.getnchannels
()
返回音频的通道数(单声道为 1,立体声为 2)。
aifc.getsampwidth
()
返回以字节表示的单个采样的大小。
aifc.getframerate
()
返回采样率(每秒的音频帧数)。
aifc.getnframes
()
返回文件中的音频帧总数。
aifc.getcomptype
()
返回一个长度为 4 的字节数组,描述了音频文件中使用的压缩类型。对于 AIFF 文件,返回值为 b'NONE'
。
aifc.getcompname
()
返回一个字节数组,可转换为人类可读的描述,描述的是音频文件中使用的压缩类型。对于 AIFF 文件,返回值为 b'not compressed'
。
aifc.getparams
()
返回一个 namedtuple()
(nchannels, sampwidth, framerate, nframes, comptype, compname)
,与 get*()
方法的输出相同。
aifc.getmarkers
()
返回一个列表,包含音频文件中的所有标记。标记由一个 3 元素的元组组成。第一个元素是标记 ID(整数),第二个是标记位置,从数据开头算起的帧数(整数),第三个是标记的名称(字符串)。
aifc.getmark
(id)
根据传入的标记 id 返回元组,元组与 getmarkers()
中描述的一致。
aifc.readframes
(nframes)
从音频文件读取并返回后续 nframes 个帧。返回的数据是一个字符串,包含每个帧所有通道的未压缩采样值。
aifc.rewind
()
倒回读取指针。下一次 readframes()
将从头开始。
aifc.setpos
(pos)
移动读取指针到指定的帧上。
aifc.tell
()
返回当前的帧号。
aifc.close
()
关闭 AIFF 文件。调用此方法后,对象将无法再使用。
打开文件用于写入时,open()
返回的对象具有上述所有方法,但 readframes()
和 setpos()
除外,并额外具备了以下方法。只有调用了 set*()
方法之后,才能调用相应的 get*()
方法。在首次调用 writeframes()
或 writeframesraw()
之前,必须填写除帧数以外的所有参数。
aifc.aiff
()
创建一个 AIFF 文件,默认创建 AIFF-C 文件,除非文件名以 '.aiff'
为后缀,在此情况下默认创建 AIFF 文件。
aifc.aifc
()
创建一个 AIFF-C 文件。 默认创建 AIFF-C 文件,除非文件名以 '.aiff'
为后缀,在此情况下默认创建 AIFF 文件。
aifc.setnchannels
(nchannels)
指明音频文件中的通道数。
aifc.setsampwidth
(width)
指明以字节为单位的音频采样大小。
aifc.setframerate
(rate)
指明以每秒帧数表示的采样频率。
aifc.setnframes
(nframes)
指明要写入到音频文件的帧数。 如果未设定此形参或者未正确设定,则文件需要支持位置查找。
aifc.setcomptype
(type, name)
指明压缩类型。 如果未指明,则音频数据将不会被压缩。 在 AIFF 文件中,压缩是无法实现的。 name 形参应当为以字节数组表示的人类可读的压缩类型描述,type 形参应当为长度为 4 的字节数组。 目前支持的压缩类型如下: b'NONE'
, b'ULAW'
, b'ALAW'
, b'G722'
。
aifc.setparams
(nchannels, sampwidth, framerate, comptype, compname)
一次性设置上述所有参数。 该参数是由多个形参组成的元组。 这意味着可以使用 getparams()
调用的结果作为 setparams()
的参数。
aifc.setmark
(id, pos, name)
添加具有给定 id (大于 0),以及在给定位置上给定名称的标记。 此方法可在 close()
之前的任何时候被调用。
aifc.tell
()
返回输出文件中的当前写入位置。 适用于与 setmark()
进行协同配合。
aifc.writeframes
(data)
将数据写入到输出文件。 此方法只能在设置了音频文件形参之后被调用。
在 3.4 版更改: 现在可接受任意 bytes-like object。
aifc.writeframesraw
(data)
类似于 writeframes()
,不同之处在于音频文件的标头不会被更新。
在 3.4 版更改: 现在可接受任意 bytes-like object。
aifc.close
()
关闭 AIFF 文件。 文件的标头会被更新以反映音频数据的实际大小。 在调用此方法之后,对象将无法再被使用。
sunau
—- 读写 Sun AU 文件
源代码: Lib/sunau.py
sunau
模拟提供了一个处理 Sun AU 声音格式的便利接口。请注意此模块与 aifc
和 wave
是兼容接口的。
音频文件由标头和数据组成。标头的字段为:
域 | 目录 |
---|---|
magic word | 四个字节 .snd |
header size | 标头的大小,包括信息,以字节为单位。 |
data size | 数据的物理大小,以字节为单位。 |
编码 | 指示音频样本的编码方式。 |
sample rate | 采样率 |
# of channels | 采样中的通道数。 |
info | 提供音频文件描述的ASCII字符串(用空字节填充)。 |
Apart from the info field, all header fields are 4 bytes in size. They are all 32-bit unsigned integers encoded in big-endian byte order.
The sunau
module defines the following functions:
sunau.open
(file, mode)
If file is a string, open the file by that name, otherwise treat it as a seekable file-like object. mode can be any of
'r'
只读模式。
'w'
只写模式。
Note that it does not allow read/write files.
A mode of 'r'
returns an AU_read
object, while a mode of 'w'
or 'wb'
returns an AU_write
object.
The sunau
module defines the following exception:
exception sunau.Error
An error raised when something is impossible because of Sun AU specs or implementation deficiency.
The sunau
module defines the following data items:
sunau.AUDIO_FILE_MAGIC
An integer every valid Sun AU file begins with, stored in big-endian form. This is the string .snd
interpreted as an integer.
sunau.AUDIO_FILE_ENCODING_MULAW_8
sunau.AUDIO_FILE_ENCODING_LINEAR_8
sunau.AUDIO_FILE_ENCODING_LINEAR_16
sunau.AUDIO_FILE_ENCODING_LINEAR_24
sunau.AUDIO_FILE_ENCODING_LINEAR_32
sunau.AUDIO_FILE_ENCODING_ALAW_8
Values of the encoding field from the AU header which are supported by this module.
sunau.AUDIO_FILE_ENCODING_FLOAT
sunau.AUDIO_FILE_ENCODING_DOUBLE
sunau.AUDIO_FILE_ENCODING_ADPCM_G721
sunau.AUDIO_FILE_ENCODING_ADPCM_G722
sunau.AUDIO_FILE_ENCODING_ADPCM_G723_3
sunau.AUDIO_FILE_ENCODING_ADPCM_G723_5
Additional known values of the encoding field from the AU header, but which are not supported by this module.
AU_read 对象
AU_read objects, as returned by open()
above, have the following methods:
AU_read.close
()
Close the stream, and make the instance unusable. (This is called automatically on deletion.)
AU_read.getnchannels
()
Returns number of audio channels (1 for mono, 2 for stereo).
AU_read.getsampwidth
()
返回采样字节长度。
AU_read.getframerate
()
返回采样频率。
AU_read.getnframes
()
返回音频总帧数。
AU_read.getcomptype
()
Returns compression type. Supported compression types are 'ULAW'
, 'ALAW'
and 'NONE'
.
AU_read.getcompname
()
Human-readable version of getcomptype()
. The supported types have the respective names 'CCITT G.711 u-law'
, 'CCITT G.711 A-law'
and 'not compressed'
.
AU_read.getparams
()
返回一个 namedtuple()
(nchannels, sampwidth, framerate, nframes, comptype, compname)
,与 get*()
方法的输出相同。
AU_read.readframes
(n)
Reads and returns at most n frames of audio, as a bytes
object. The data will be returned in linear format. If the original data is in u-LAW format, it will be converted.
AU_read.rewind
()
重置文件指针至音频开头.
以下两个方法都使用指针,具体实现由其底层决定。
AU_read.setpos
(pos)
Set the file pointer to the specified position. Only values returned from tell()
should be used for pos.
AU_read.tell
()
Return current file pointer position. Note that the returned value has nothing to do with the actual position in the file.
The following two functions are defined for compatibility with the aifc
, and don’t do anything interesting.
AU_read.getmarkers
()
返回 None
。
AU_read.getmark
(id)
引发错误异常。
AU_write 对象
AU_write objects, as returned by open()
above, have the following methods:
AU_write.setnchannels
(n)
设置声道数。
AU_write.setsampwidth
(n)
Set the sample width (in bytes.)
在 3.4 版更改: Added support for 24-bit samples.
AU_write.setframerate
(n)
Set the frame rate.
AU_write.setnframes
(n)
Set the number of frames. This can be later changed, when and if more frames are written.
AU_write.setcomptype
(type, name)
Set the compression type and description. Only 'NONE'
and 'ULAW'
are supported on output.
AU_write.setparams
(tuple)
The tuple should be (nchannels, sampwidth, framerate, nframes, comptype, compname)
, with values valid for the set*()
methods. Set all parameters.
AU_write.tell
()
Return current position in the file, with the same disclaimer for the AU_read.tell()
and AU_read.setpos()
methods.
AU_write.writeframesraw
(data)
写入音频数据但不更新 nframes。
在 3.4 版更改: 现在可接受任意 bytes-like object。
AU_write.writeframes
(data)
写入音频数据并更新 nframes。
在 3.4 版更改: 现在可接受任意 bytes-like object。
AU_write.close
()
Make sure nframes is correct, and close the file.
This method is called upon deletion.
Note that it is invalid to set any parameters after calling writeframes()
or writeframesraw()
.
wave
—- 读写WAV格式文件
源代码: Lib/wave.py
wave
模块提供了一个处理 WAV 声音格式的便利接口。它不支持压缩/解压,但是支持单声道/立体声。
wave
模块定义了以下函数和异常:
wave.open
(file, mode=None)
如果 file 是一个字符串,打开对应文件名的文件。否则就把它作为文件类对象来处理。mode 可以为以下值:
'rb'
只读模式。
'wb'
只写模式。
注意不支持同时读写WAV文件。
mode 设为 'rb'
时返回一个 Wave_read
对象,而 mode 设为 'wb'
时返回一个 Wave_write
对象。如果省略 mode 并指定 file 来传入一个文件类对象,则 file.mode
会被用作 mode 的默认值。
如果操作的是文件对象,当使用 wave 对象的 close()
方法时,并不会真正关闭文件对象,这需要调用者负责来关闭文件对象。
open()
函数可以在 with
语句中使用。 当 with
阻塞结束时,Wave_read.close()
或 Wave_write.close()
方法会被调用。
在 3.4 版更改: 添加了对不可搜索文件的支持。
exception wave.Error
当不符合WAV格式或无法操作时引发的错误。
Wave_read对象
由 open()
返回的 Wave_read 对象,有以下几种方法:
Wave_read.close
()
关闭 wave
打开的数据流并使对象不可用。当对象销毁时会自动调用。
Wave_read.getnchannels
()
返回声道数量(1
为单声道,2
为立体声)
Wave_read.getsampwidth
()
返回采样字节长度。
Wave_read.getframerate
()
返回采样频率。
Wave_read.getnframes
()
返回音频总帧数。
Wave_read.getcomptype
()
返回压缩类型(只支持 'NONE'
类型)
Wave_read.getcompname
()
getcomptype()
的通俗版本。使用 'not compressed'
代替 'NONE'
。
Wave_read.getparams
()
返回一个 namedtuple()
(nchannels, sampwidth, framerate, nframes, comptype, compname)
,与 get*()
方法的输出相同。
Wave_read.readframes
(n)
读取并返回以 bytes
对象表示的最多 n 帧音频。
Wave_read.rewind
()
重置文件指针至音频开头.
后面两个方法是为了和 aifc
保持兼容,实际不做任何事情。
Wave_read.getmarkers
()
返回 None
。
Wave_read.getmark
(id)
引发错误异常。
以下两个方法都使用指针,具体实现由其底层决定。
Wave_read.setpos
(pos)
设置文件指针到指定位置。
Wave_read.tell
()
返回当前文件指针位置。
Wave_write 对象
对于可查找的输出流,wave
头将自动更新以反映实际写入的帧数。 对于不可查找的流,当写入第一帧时 nframes 值必须准确。 获取准确的 nframes 值可以通过调用 setnframes()
或 setparams()
并附带 close()
被调用之前将要写入的帧数,然后使用 writeframesraw()
来写入帧数据,或者通过调用 writeframes()
并附带所有要写入的帧。 在后一种情况下 writeframes()
将计算数据中的帧数并在写入帧数据之前相应地设置 nframes。
由 open()
返回的 Wave_write 对象,有以下几种方法:
在 3.4 版更改: 添加了对不可搜索文件的支持。
Wave_write.close
()
确保 nframes 是正确的,并在文件被 wave
打开时关闭它。 此方法会在对象收集时被调用。 如果输出流不可查找且 nframes 与实际写入的帧数不匹配时引发异常。
Wave_write.setnchannels
(n)
设置声道数。
Wave_write.setsampwidth
(n)
设置采样字节长度为 n。
Wave_write.setframerate
(n)
设置采样频率为 n。
在 3.2 版更改: 对此方法的非整数输入会被舍入到最接近的整数。
Wave_write.setnframes
(n)
设置总帧数为 n。 如果与之后实际写入的帧数不一致此值将会被更改( 如果输出流不可查找则此更改尝试将引发错误)。
Wave_write.setcomptype
(type, name)
设置压缩格式。目前只支持 NONE
即无压缩格式。
Wave_write.setparams
(tuple)
tuple 应该是 (nchannels, sampwidth, framerate, nframes, comptype, compname)
,每项的值应可用于 set*()
方法。设置所有形参。
Wave_write.tell
()
返回当前文件指针,其指针含义和 Wave_read.tell()
以及 Wave_read.setpos()
是一致的。
Wave_write.writeframesraw
(data)
写入音频数据但不更新 nframes。
在 3.4 版更改: 现在可接受任意 bytes-like object。
Wave_write.writeframes
(data)
写入音频帧并确保 nframes 是正确的。 如果输出流不可查找且在 data 被写入之后写入的总帧数与之前设定的has been written does not match the previously set value for nframes 值不匹配将会引发错误。
在 3.4 版更改: 现在可接受任意 bytes-like object。
注意在调用 writeframes()
或 writeframesraw()
之后再设置任何格式参数是无效的,而且任何这样的尝试将引发 wave.Error
。
chunk
—- 读取 IFF 分块数据
源代码: Lib/chunk.py
本模块提供了一个读取使用 EA IFF 85 分块的数据的接口chunks. 1 这种格式使用的场合有 Audio Interchange File Format (AIFF/AIFF-C) 和 Real Media File Format (RMFF) 等。 与它们密切相关的 WAVE 音频文件也可使用此模块来读取。
一个分块具有以下结构:
偏移 | 长度 | 目录 |
---|---|---|
0 | 4 | 区块ID |
4 | 4 | 大端字节顺序的块大小,不包括头 |
8 | n | 数据字节,其中 n 是前一字段中给出的大小 |
8 + n | 0 或 1 | 如果 n 为奇数且使用块对齐,则需要填充字节 |
ID是一个4字节的字符串,用于标识块的类型。
大小字段(32 位的值,使用大端字节序编码)给出分块数据的大小,不包括 8 字节的标头。
使用由一个或更多分块组成的 IFF 类型文件。 此处定义的 Chunk
类的建议使用方式是在每个分块开始时实例化一个实例并从实例读取直到其末尾,在那之后可以再实例化新的实例。 到达文件末尾时,创建新实例将会失败并引发 EOFError
异常。
class chunk.Chunk
(file, align=True, bigendian=True, inclheader=False)
代表一个分块的类。 file 参数预期为一个文件类对象。 特别地也允许该类的实例。 唯一必需的方法是 read()
。 如果存在 seek()
和 tell()
方法并且没有引发异常,它们也会被使用。 如果存在这些方法并且引发了异常,则它们不应改变目标对象。 如果可选参数 align 为真值,则分块应当以 2 字节边界对齐。 如果 align 为假值,则不使用对齐。 此参数默认为真值。 如果可选参数 bigendian 为假值,分块大小应当为小端序。 这对于 WAVE 音频文件是必须的。 此参数默认为真值。 如果可选参数 inclheader 为真值,则分块标头中给出的大小将包括标头的大小。 此参数默认为假值。
Chunk
对象支持下列方法:
getname
()返回分块的名称(ID)。 这是分块的头 4 个字节。
getsize
()返回分块的大小。
close
()关闭并跳转到分块的末尾。 这不会关闭下层的文件。
在 close()
方法已被调用后其余方法将会引发 OSError
。 在 Python 3.3 之前,它们曾会引发 IOError
,现在这是 OSError
的一个别名。
isatty
()返回
False
。seek
(pos, whence=0)设置分块的当前位置。 whence 参数为可选项并且默认为
0
(绝对文件定位);其他值还有1
(相对当前位置查找) 和2
(相对文件末尾查找)。 没有返回值。 如果下层文件不支持查找,则只允许向前查找。tell
()将当前位置返回到分块。
read
(size=- 1)从分块读取至多 size 个字节(如果在获得 size 个字节之前已到达分块末尾则读取的字节会少于此数量)。 如果 size 参数为负值或被省略,则读取所有字节直到分块末尾。 当立即遇到分块末尾则返回空字节串对象。
skip
()跳到分块末尾。此后对分块再次调用
read()
将返回b''
。 如果你对分块的内容不感兴趣,则应当调用此方法以使文件指向下一分块的开头。
colorsys
—- 颜色系统间的转换
源代码: Lib/colorsys.py
colorsys
模块定义了计算机显示器所用的 RGB (Red Green Blue) 色彩空间与三种其他色彩坐标系统 YIQ, HLS (Hue Lightness Saturation) 和 HSV (Hue Saturation Value) 表示的颜色值之间的双向转换。 所有这些色彩空间的坐标都使用浮点数值来表示。 在 YIQ 空间中,Y 坐标取值为 0 和 1 之间,而 I 和 Q 坐标均可以为正数或负数。 在所有其他空间中,坐标取值均为 0 和 1 之间。
参见
有关色彩空间的更多信息可访问 https://poynton.ca/ColorFAQ.html 和 https://www.cambridgeincolour.com/tutorials/color-spaces.htm。
colorsys
模块定义了如下函数:
colorsys.rgb_to_yiq
(r, g, b)
把颜色从RGB值转为YIQ值。
colorsys.yiq_to_rgb
(y, i, q)
把颜色从YIQ值转为RGB值。
colorsys.rgb_to_hls
(r, g, b)
把颜色从RGB值转为HLS值。
colorsys.hls_to_rgb
(h, l, s)
把颜色从HLS值转为RGB值。
colorsys.rgb_to_hsv
(r, g, b)
把颜色从RGB值转为HSV值。
colorsys.hsv_to_rgb
(h, s, v)
把颜色从HSV值转为RGB值。
示例:
>>> import colorsys
>>> colorsys.rgb_to_hsv(0.2, 0.4, 0.4)
(0.5, 0.5, 0.4)
>>> colorsys.hsv_to_rgb(0.5, 0.5, 0.4)
(0.2, 0.4, 0.4)
imghdr
—- 推测图像类型
源代码 Lib/imghdr.py
imghdr
模块推测文件或字节流中的图像的类型。
imghdr
模块定义了以下类型:
imghdr.what
(file, h=None)
测试包含在名为 file 的文件中的图像数据,并返回描述该图像类型的字符串。 如果提供了可选的 h,则 file 参数会被忽略并且 h 会被视为包含要测试的字节流。
在 3.6 版更改: 接受一个 path-like object。
接下来的图像类型是可识别的,返回值来自 what()
:
值 | 图像格式 |
---|---|
‘rgb’ |
SGI 图像库文件 |
‘gif’ |
GIF 87a 和 89a 文件 |
‘pbm’ |
便携式位图文件 |
‘pgm’ |
便携式灰度图文件 |
‘ppm’ |
便携式像素表文件 |
‘tiff’ |
TIFF 文件 |
‘rast’ |
Sun 光栅文件 |
‘xbm’ |
X 位图文件 |
‘jpeg’ |
JFIF 或 Exif 格式的 JPEG 数据 |
‘bmp’ |
BMP 文件 |
‘png’ |
便携式网络图像 |
‘webp’ |
WebP 文件 |
‘exr’ |
OpenEXR 文件 |
3.5 新版功能: exr 和 webp 格式被添加。
你可以扩展此 imghdr
可以被追加的这个变量识别的文件格式的列表:
imghdr.tests
执行单个测试的函数列表。每个函数都有两个参数:字节流和类似开放文件的对象。当 what()
用字节流调用时,类文件对象将是 None
。
如果测试成功,这个测试函数应当返回一个描述图像类型的字符串,否则返回 None
。
示例:
>>> import imghdr
>>> imghdr.what('bass.gif')
'gif'
sndhdr
—- 推测声音文件的类型
源代码 Lib/sndhdr.py
sndhdr
提供了企图猜测文件中的声音数据类型的功能函数。当这些函数可以推测出存储在文件中的声音数据的类型是,它们返回一个 collections.namedtuple()
,包含了五种属性:(filetype
, framerate
, nchannels
, nframes
, sampwidth
)。这些 type 的值表示数据的类型,会是以下字符串之一: 'aifc'
, 'aiff'
, 'au'
, 'hcom'
, 'sndr'
, 'sndt'
, 'voc'
, 'wav'
, '8svx'
, 'sb'
, 'ub'
, or 'ul'
。 sampling_rate 可能是实际值或者当未知或者难以解码时的 0
。类似的, channels 也会返回实际值或者在无法推测或者难以解码时返回 0
。 frames 则是实际值或 -1
。 元组的最后一项, bits_per_sample 将会为比特表示的 sample 大小或者 A-LAW 时为 'A'
, u-LAW 时为 'U'
。
sndhdr.what
(filename)
使用 whathdr()
推测存储在 filename 文件中的声音数据的类型。如果成功,返回上述的命名元组,否则返回 None
。
在 3.5 版更改: 将结果从元组改为命名元组。
sndhdr.whathdr
(filename)
基于文件头推测存储在文件中的声音数据类型。文件名由 filename 给出。这个函数在成功时返回上述命名元组,或者在失败时返回 None
。
在 3.5 版更改: 将结果从元组改为命名元组。
ossaudiodev
—- 访问兼容OSS的音频设备
该模块允许您访问 OSS(开放式音响系统)音频接口。 OSS 可用于广泛的开源和商业 Unices,并且是 Linux 和最新版本的 FreeBSD 的标准音频接口。
在 3.3 版更改: 此模块中过去会引发 IOError
的操作现在将引发 OSError
。
参见
OSS C API 的官方文档
该模块定义了大量由OSS设备驱动提供的常量; 请参阅<sys/soundcard.h>
Linux 或 FreeBSD 上的列表。
ossaudiodev
defines the following variables and functions:
exception ossaudiodev.OSSAudioError
This exception is raised on certain errors. The argument is a string describing what went wrong.
(If ossaudiodev
receives an error from a system call such as open()
, write()
, or ioctl()
, it raises OSError
. Errors detected directly by ossaudiodev
result in OSSAudioError
.)
(For backwards compatibility, the exception class is also available as ossaudiodev.error
.)
ossaudiodev.open
(mode)
ossaudiodev.open
(device, mode)
Open an audio device and return an OSS audio device object. This object supports many file-like methods, such as read()
, write()
, and fileno()
(although there are subtle differences between conventional Unix read/write semantics and those of OSS audio devices). It also supports a number of audio-specific methods; see below for the complete list of methods.
device is the audio device filename to use. If it is not specified, this module first looks in the environment variable AUDIODEV
for a device to use. If not found, it falls back to /dev/dsp
.
mode is one of 'r'
for read-only (record) access, 'w'
for write-only (playback) access and 'rw'
for both. Since many sound cards only allow one process to have the recorder or player open at a time, it is a good idea to open the device only for the activity needed. Further, some sound cards are half-duplex: they can be opened for reading or writing, but not both at once.
Note the unusual calling syntax: the first argument is optional, and the second is required. This is a historical artifact for compatibility with the older linuxaudiodev
module which ossaudiodev
supersedes.
ossaudiodev.openmixer
([device])
Open a mixer device and return an OSS mixer device object. device is the mixer device filename to use. If it is not specified, this module first looks in the environment variable MIXERDEV
for a device to use. If not found, it falls back to /dev/mixer
.
Audio Device Objects
Before you can write to or read from an audio device, you must call three methods in the correct order:
setfmt()
to set the output formatchannels()
to set the number of channelsspeed()
to set the sample rate
Alternately, you can use the setparameters()
method to set all three audio parameters at once. This is more convenient, but may not be as flexible in all cases.
The audio device objects returned by open()
define the following methods and (read-only) attributes:
oss_audio_device.close
()
Explicitly close the audio device. When you are done writing to or reading from an audio device, you should explicitly close it. A closed device cannot be used again.
oss_audio_device.fileno
()
Return the file descriptor associated with the device.
oss_audio_device.read
(size)
Read size bytes from the audio input and return them as a Python string. Unlike most Unix device drivers, OSS audio devices in blocking mode (the default) will block read()
until the entire requested amount of data is available.
oss_audio_device.write
(data)
Write a bytes-like object data to the audio device and return the number of bytes written. If the audio device is in blocking mode (the default), the entire data is always written (again, this is different from usual Unix device semantics). If the device is in non-blocking mode, some data may not be written—-see writeall()
.
在 3.5 版更改: 现在接受可写的 字节类对象。
oss_audio_device.writeall
(data)
Write a bytes-like object data to the audio device: waits until the audio device is able to accept data, writes as much data as it will accept, and repeats until data has been completely written. If the device is in blocking mode (the default), this has the same effect as write()
; writeall()
is only useful in non-blocking mode. Has no return value, since the amount of data written is always equal to the amount of data supplied.
在 3.5 版更改: 现在接受可写的 字节类对象。
在 3.2 版更改: Audio device objects also support the context management protocol, i.e. they can be used in a with
statement.
The following methods each map to exactly one ioctl()
system call. The correspondence is obvious: for example, setfmt()
corresponds to the SNDCTL_DSP_SETFMT
ioctl, and sync()
to SNDCTL_DSP_SYNC
(this can be useful when consulting the OSS documentation). If the underlying ioctl()
fails, they all raise OSError
.
oss_audio_device.nonblock
()
Put the device into non-blocking mode. Once in non-blocking mode, there is no way to return it to blocking mode.
oss_audio_device.getfmts
()
Return a bitmask of the audio output formats supported by the soundcard. Some of the formats supported by OSS are:
格式 | 描述 |
---|---|
AFMT_MU_LAW |
a logarithmic encoding (used by Sun .au files and /dev/audio ) |
AFMT_A_LAW |
a logarithmic encoding |
AFMT_IMA_ADPCM |
a 4:1 compressed format defined by the Interactive Multimedia Association |
AFMT_U8 |
Unsigned, 8-bit audio |
AFMT_S16_LE |
Signed, 16-bit audio, little-endian byte order (as used by Intel processors) |
AFMT_S16_BE |
Signed, 16-bit audio, big-endian byte order (as used by 68k, PowerPC, Sparc) |
AFMT_S8 |
Signed, 8 bit audio |
AFMT_U16_LE |
Unsigned, 16-bit little-endian audio |
AFMT_U16_BE |
Unsigned, 16-bit big-endian audio |
Consult the OSS documentation for a full list of audio formats, and note that most devices support only a subset of these formats. Some older devices only support AFMT_U8
; the most common format used today is AFMT_S16_LE
.
oss_audio_device.setfmt
(format)
Try to set the current audio format to format-—see getfmts()
for a list. Returns the audio format that the device was set to, which may not be the requested format. May also be used to return the current audio format—-do this by passing an “audio format” of AFMT_QUERY
.
oss_audio_device.channels
(nchannels)
Set the number of output channels to nchannels. A value of 1 indicates monophonic sound, 2 stereophonic. Some devices may have more than 2 channels, and some high-end devices may not support mono. Returns the number of channels the device was set to.
oss_audio_device.speed
(samplerate)
Try to set the audio sampling rate to samplerate samples per second. Returns the rate actually set. Most sound devices don’t support arbitrary sampling rates. Common rates are:
采样率 | 描述 |
---|---|
8000 | /dev/audio 的默认采样率 |
11025 | 语音录音 |
22050 | |
44100 | CD品质的音频(16位采样和2通道) |
96000 | DVD品质的音频(24位采样) |
oss_audio_device.sync
()
Wait until the sound device has played every byte in its buffer. (This happens implicitly when the device is closed.) The OSS documentation recommends closing and re-opening the device rather than using sync()
.
oss_audio_device.reset
()
Immediately stop playing or recording and return the device to a state where it can accept commands. The OSS documentation recommends closing and re-opening the device after calling reset()
.
oss_audio_device.post
()
Tell the driver that there is likely to be a pause in the output, making it possible for the device to handle the pause more intelligently. You might use this after playing a spot sound effect, before waiting for user input, or before doing disk I/O.
The following convenience methods combine several ioctls, or one ioctl and some simple calculations.
oss_audio_device.setparameters
(format, nchannels, samplerate[, strict=False])
Set the key audio sampling parameters—-sample format, number of channels, and sampling rate—-in one method call. format, nchannels, and samplerate should be as specified in the setfmt()
, channels()
, and speed()
methods. If strict is true, setparameters()
checks to see if each parameter was actually set to the requested value, and raises OSSAudioError
if not. Returns a tuple (format, nchannels, samplerate) indicating the parameter values that were actually set by the device driver (i.e., the same as the return values of setfmt()
, channels()
, and speed()
).
For example,
(fmt, channels, rate) = dsp.setparameters(fmt, channels, rate)
is equivalent to
fmt = dsp.setfmt(fmt)
channels = dsp.channels(channels)
rate = dsp.rate(rate)
oss_audio_device.bufsize
()
Returns the size of the hardware buffer, in samples.
oss_audio_device.obufcount
()
Returns the number of samples that are in the hardware buffer yet to be played.
oss_audio_device.obuffree
()
Returns the number of samples that could be queued into the hardware buffer to be played without blocking.
Audio device objects also support several read-only attributes:
oss_audio_device.closed
Boolean indicating whether the device has been closed.
oss_audio_device.name
String containing the name of the device file.
oss_audio_device.mode
The I/O mode for the file, either "r"
, "rw"
, or "w"
.
Mixer Device Objects
The mixer object provides two file-like methods:
oss_mixer_device.close
()
This method closes the open mixer device file. Any further attempts to use the mixer after this file is closed will raise an OSError
.
oss_mixer_device.fileno
()
Returns the file handle number of the open mixer device file.
在 3.2 版更改: Mixer objects also support the context management protocol.
The remaining methods are specific to audio mixing:
oss_mixer_device.controls
()
This method returns a bitmask specifying the available mixer controls (“Control” being a specific mixable “channel”, such as SOUND_MIXER_PCM
or SOUND_MIXER_SYNTH
). This bitmask indicates a subset of all available mixer controls—-the SOUND_MIXER_*
constants defined at module level. To determine if, for example, the current mixer object supports a PCM mixer, use the following Python code:
mixer=ossaudiodev.openmixer()
if mixer.controls() & (1 << ossaudiodev.SOUND_MIXER_PCM):
# PCM is supported
... code ...
For most purposes, the SOUND_MIXER_VOLUME
(master volume) and SOUND_MIXER_PCM
controls should suffice—-but code that uses the mixer should be flexible when it comes to choosing mixer controls. On the Gravis Ultrasound, for example, SOUND_MIXER_VOLUME
does not exist.
oss_mixer_device.stereocontrols
()
Returns a bitmask indicating stereo mixer controls. If a bit is set, the corresponding control is stereo; if it is unset, the control is either monophonic or not supported by the mixer (use in combination with controls()
to determine which).
See the code example for the controls()
function for an example of getting data from a bitmask.
oss_mixer_device.reccontrols
()
Returns a bitmask specifying the mixer controls that may be used to record. See the code example for controls()
for an example of reading from a bitmask.
oss_mixer_device.get
(control)
Returns the volume of a given mixer control. The returned volume is a 2-tuple (left_volume,right_volume)
. Volumes are specified as numbers from 0 (silent) to 100 (full volume). If the control is monophonic, a 2-tuple is still returned, but both volumes are the same.
Raises OSSAudioError
if an invalid control is specified, or OSError
if an unsupported control is specified.
oss_mixer_device.set
(control, (left, right))
Sets the volume for a given mixer control to (left,right)
. left
and right
must be ints and between 0 (silent) and 100 (full volume). On success, the new volume is returned as a 2-tuple. Note that this may not be exactly the same as the volume specified, because of the limited resolution of some soundcard’s mixers.
Raises OSSAudioError
if an invalid mixer control was specified, or if the specified volumes were out-of-range.
oss_mixer_device.get_recsrc
()
This method returns a bitmask indicating which control(s) are currently being used as a recording source.
oss_mixer_device.set_recsrc
(bitmask)
Call this function to specify a recording source. Returns a bitmask indicating the new recording source (or sources) if successful; raises OSError
if an invalid source was specified. To set the current recording source to the microphone input:
mixer.setrecsrc (1 << ossaudiodev.SOUND_MIXER_MIC)
国际化
本章中描述的模块列表是:
gettext
—- 多语种国际化服务- GNU gettext API
- 基于类的 API
NullTranslations
类GNUTranslations
类- Solaris 消息编目支持
- 编目构造器
- 国际化 (I18N) 你的程序和模块
- 本地化你的模块
- 本地化你的应用程序
- 即时更改语言
- 延迟翻译
locale
—- 国际化服务- Background, details, hints, tips and caveats
- For extension writers and programs that embed Python
- Access to message catalogs
gettext
—- 多语种国际化服务
源代码: Lib/gettext.py
gettext
模块为 Python 模块和应用程序提供国际化 (Internationalization, I18N) 和本地化 (Localization, L10N) 服务。它同时支持 GNU gettext 消息编目 API 和更高级的、基于类的 API,后者可能更适合于 Python 文件。下方描述的接口允许用户使用一种自然语言编写模块和应用程序消息,并提供翻译后的消息编目,以便在不同的自然语言下运行。
同时还给出一些本地化 Python 模块及应用程序的小技巧。
GNU gettext API
模块 gettext
定义了下列 API,这与 gettext API 类似。如果你使用该 API,将会对整个应用程序产生全局的影响。如果你的应用程序支持多语种,而语言选择取决于用户的语言环境设置,这通常正是你所想要的。而如果你正在本地化某个 Python 模块,或者你的应用程序需要在运行时切换语言,相反你或许想用基于类的API。
gettext.bindtextdomain
(domain, localedir=None)
将 domain 绑定到本地目录 localedir。 更具体地来说,模块 gettext
将使用路径 (在 Unix 系统中): `localedir/language/LC_MESSAGES/domain.mo查找二进制
.mo文件,此处对应地查找 *language* 的位置是环境变量
LANGUAGE,
LC_ALL,
LC_MESSAGES和
LANG` 中。
如果遗漏了 localedir 或者设置为 None
,那么将返回当前 domain 所绑定的值
gettext.bind_textdomain_codeset
(domain, codeset=None)
将 domain 绑定到 codeset,修改 lgettext()
, ldgettext()
, lngettext()
和 ldngettext()
函数返回的字节串的字符编码。如果省略了 codeset,则返回当前绑定的编码集。
Deprecated since version 3.8, removed in version 3.10.
gettext.textdomain
(domain=None)
修改或查询当前的全局域。如果 domain 为 None
,则返回当前的全局域,不为 None
则将全局域设置为 domain,并返回它。
gettext.gettext
(message)
返回 message 的本地化翻译,依据包括当前的全局域、语言和语言环境目录。本函数在本地命名空间中通常有别名 _()
(参考下面的示例)。
gettext.dgettext
(domain, message)
与 gettext()
类似,但在指定的 domain 中查找 message。
gettext.ngettext
(singular, plural, n)
与 gettext()
类似,但考虑了复数形式。如果找到了翻译,则将 n 代入复数公式,然后返回得出的消息(某些语言具有两种以上的复数形式)。如果未找到翻译,则 n 为 1 时返回 singular,为其他数时返回 plural。
复数公式取自编目头文件。它是 C 或 Python 表达式,有一个自变量 n,该表达式计算的是所需复数形式在编目中的索引号。关于在 .po
文件中使用的确切语法和各种语言的公式。
gettext.dngettext
(domain, singular, plural, n)
与 ngettext()
类似,但在指定的 domain 中查找 message。
gettext.pgettext
(context, message)
gettext.dpgettext
(domain, context, message)
gettext.npgettext
(context, singular, plural, n)
gettext.dnpgettext
(domain, context, singular, plural, n)
与前缀中没有 p
的相应函数类似(即 gettext()
, dgettext()
, ngettext()
, dngettext()
),但是仅翻译给定的 message context。
3.8 新版功能.
gettext.lgettext
(message)
gettext.ldgettext
(domain, message)
gettext.lngettext
(singular, plural, n)
gettext.ldngettext
(domain, singular, plural, n)
与前缀中没有 l
的相应函数等效( gettext()
, dgettext()
, ngettext()
和 dngettext()
),但是如果没有用 bind_textdomain_codeset()
显式设置其他编码,则返回的翻译将以首选系统编码来编码字节串。
警告
在 Python 3 中应避免使用这些函数,因为它们返回的是编码后的字节串。最好使用返回 Unicode 字符串的其他方法,因为大多数 Python 应用程序都希望将人类可读的文本作为字符串而不是字节来处理。此外,如果翻译后的字符串存在编码问题,则可能会意外出现与 Unicode 相关的异常。
Deprecated since version 3.8, removed in version 3.10.
注意,GNU gettext 还定义了 dcgettext()
方法,但它被认为不实用,因此目前没有实现它。
这是该 API 的典型用法示例:
import gettext
gettext.bindtextdomain('myapplication', '/path/to/my/language/directory')
gettext.textdomain('myapplication')
_ = gettext.gettext
# ...
print(_('This is a translatable string.'))
基于类的 API
与 GNU gettext API 相比,gettext
模块的基于类的 API 提供了更多的灵活性和更强的便利性。这是本地化 Python 应用程序和模块的推荐方法。gettext
定义了一个 GNUTranslations
类,该类实现了 GNU .mo
格式文件的解析,并且具有用于返回字符串的方法。本类的实例也可以将自身作为函数 _()
安装到内建命名空间中。
gettext.find
(domain, localedir=None, languages=None, all=False)
本函数实现了标准的 .mo
文件搜索算法。它接受一个 domain*,它与 textdomain()
接受的域相同。可选参数 *localedir 与 bindtextdomain()
中的相同。可选参数 languages 是多条字符串的列表,其中每条字符串都是一种语言代码。
如果没有传入 localedir,则使用默认的系统语言环境目录。如果没有传入 *languages,则搜索以下环境变量:LANGUAGE
、LC_ALL
、LC_MESSAGES
和 LANG
。从这些变量返回的第一个非空值将用作 *languages 变量。环境变量应包含一个语言列表,由冒号分隔,该列表会被按冒号拆分,以产生所需的语言代码字符串列表。
find()
将扩展并规范化 language,然后遍历它们,搜索由这些组件构建的现有文件:
*localedir*/*language*/LC_MESSAGES/*domain*.mo
find()
返回找到类似的第一个文件名。如果找不到这样的文件,则返回 None
。如果传入了 all,它将返回一个列表,包含所有文件名,并按它们在语言列表或环境变量中出现的顺序排列。
gettext.translation
(domain, localedir=None, languages=None, class_=None, fallback=False, codeset=None)
根据 domain、localedir 和 languages,返回 *Translations
实例,首先应将前述参数传入 find()
以获取关联的 .mo
文件路径的列表。名字与 .mo
文件名相同的实例将被缓存。如果传入 class_,它将是实际被实例化的类,否则实例化 GNUTranslations
。类的构造函数必须只接受一个 文件对象 参数。如果传入 codeset,那么在 lgettext()
和 lngettext()
方法中,对翻译后的字符串进行编码的字符集将被改变。
如果找到多个文件,后找到的文件将用作先前文件的替补。为了设置替补,将使用 copy.copy()
从缓存中克隆每个 translation 对象。实际的实例数据仍在缓存中共享。
如果 .mo
文件未找到,且 fallback 为 false(默认值),则本函数引发 OSError
异常,如果 fallback 为 true,则返回一个 NullTranslations
实例。
在 3.3 版更改: 曾经是 IOError
被引发而不是 OSError
。
Deprecated since version 3.8, removed in version 3.10: codeset 参数。
gettext.install
(domain, localedir=None, codeset=None, names=None)
根据传入 translation()
函数的 domain、localedir 和 codeset,在 Python 内建命名空间中安装 _()
函数。
names 参数的信息请参阅 translation 对象的 install()
方法的描述。
如下所示,通常将字符串包括在 _()
函数的调用中,以标记应用程序中待翻译的字符串,就像这样:
print(_('This string will be translated.'))
为了方便,一般将 _()
函数安装在 Python 内建命名空间中,以便在应用程序的所有模块中轻松访问它。
Deprecated since version 3.8, removed in version 3.10: codeset 参数。
NullTranslations
类
translation 类实际实现的是,将原始源文件消息字符串转换为已翻译的消息字符串。所有 translation 类使用的基类为 NullTranslations
,它提供了基本的接口,可用于编写自己定制的 translation 类。以下是 NullTranslations
的方法:
class gettext.NullTranslations
(fp=None)
接受一个可选参数 文件对象 fp*,该参数会被基类忽略。初始化由派生类设置的 “protected” (受保护的)实例变量 *_info 和 _charset*,与 *_fallback 类似,但它是通过 add_fallback()
来设置的。如果 fp 不为 None
,就会调用 self._parse(fp)
。
_parse
(fp)在基类中没有操作,本方法接受文件对象 fp,从该文件读取数据,用来初始化消息编目。如果你手头的消息编目文件的格式不受支持,则应重写本方法来解析你的格式。
add_fallback
(fallback)添加 fallback 为当前 translation 对象的替补对象。如果 translation 对象无法为指定消息提供翻译,则应向替补查询。
gettext
(message)如果设置了替补,则转发
gettext()
给替补。否则返回 message。在派生类中被重写。ngettext
(singular, plural, n)如果设置了替补,则转发
ngettext()
给替补。否则,n 为 1 时返回 singular,为其他时返回 plural。在派生类中被重写。pgettext
(context, message)如果设置了替补,则转发
pgettext()
给替补。否则返回已翻译的消息。在派生类中被重写。3.8 新版功能.
npgettext
(context, singular, plural, n)如果设置了替补,则转发
npgettext()
给替补。否则返回已翻译的消息。在派生类中被重写。3.8 新版功能.
lgettext
(message)lngettext
(singular, plural, n)与
gettext()
和ngettext()
等效,但是如果没有用set_output_charset()
显式设置编码,则返回的翻译将以首选系统编码来编码字节串。在派生类中被重写。警告
应避免在 Python 3 中使用这些方法。
Deprecated since version 3.8, removed in version 3.10.
info
()返回 “protected”(受保护的)
_info
变量,它是一个字典,包含在消息编目文件中找到的元数据。charset
()返回消息编目文件的编码。
output_charset
()返回由
lgettext()
和lngettext()
翻译出的消息的编码。Deprecated since version 3.8, removed in version 3.10.
set_output_charset
(charset)更改翻译出的消息的编码。
Deprecated since version 3.8, removed in version 3.10.
install
(names=None)本方法将
gettext()
安装至内建命名空间,并绑定为_
。如果传入 names 参数,该参数必须是一个序列,包含除
_()
外其他要安装在内建命名空间中的函数的名称。支持的名称有'gettext'
,'ngettext'
,'pgettext'
,'npgettext'
,'lgettext'
和'lngettext'
。注意,这仅仅是使
_()
函数在应用程序中生效的一种方法,尽管也是最方便的方法。由于它会影响整个应用程序全局,特别是内建命名空间,因此已经本地化的模块不应该安装_()
,而是应该用下列代码使_()
在各自模块中生效:import gettext t = gettext.translation('mymodule', ...) _ = t.gettext
这只将
_()
放在其模块的全局命名空间中,所以只影响其模块内的调用。在 3.8 版更改: 添加了
'pgettext'
和'npgettext'
。
GNUTranslations
类
gettext
模块提供了一个派生自 NullTranslations
的其他类:GNUTranslations
。该类重写了 _parse()
,同时能以大端序和小端序格式读取 GNU gettext 格式的 .mo
文件。
GNUTranslations
从翻译编目中解析出可选的元数据。GNU gettext 约定,将元数据包括在空字符串的翻译中。该元数据采用 RFC 822 样式的 key: value
键值对,且应该包含 Project-Id-Version
键。如果找到 Content-Type
键,那么将用 charset
属性去初始化 “protected”(受保护的) _charset
实例变量,而该变量在未找到键的情况下默认为 None
。如果指定了字符编码,那么从编目中读取的所有消息 ID 和消息字符串都将使用此编码转换为 Unicode,若未指定编码,则假定编码为 ASCII。
由于消息 ID 也是作为 Unicode 字符串读取的,因此所有 *gettext()
方法都假定消息 ID 为 Unicode 字符串,而不是字节串。
整个键/值对集合将被放入一个字典,并设置为 “protected”(受保护的) _info
实例变量。
如果 .mo
文件的魔法值 (magic number) 无效,或遇到意外的主版本号,或在读取文件时发生其他问题,则实例化 GNUTranslations
类会引发 OSError
。
class gettext.GNUTranslations
下列方法是根据基类实现重写的:
gettext
(message)在编目中查找 message ID,并以 Unicode 字符串形式返回相应的消息字符串。如果在编目中没有 message ID 条目,且配置了替补,则查找请求将被转发到替补的
gettext()
方法。否则,返回 message ID。ngettext
(singular, plural, n)查找消息 ID 的复数形式。singular 用作消息 ID,用于在编目中查找,同时 n 用于确定使用哪种复数形式。返回的消息字符串是 Unicode 字符串。
如果在编目中没有找到消息 ID,且配置了替补,则查找请求将被转发到替补的
ngettext()
方法。否则,当 n 为 1 时返回 singular,其他情况返回 plural。例如:
n = len(os.listdir('.')) cat = GNUTranslations(somefile) message = cat.ngettext( 'There is %(num)d file in this directory', 'There are %(num)d files in this directory', n) % {'num': n}
pgettext
(context, message)在编目中查找 context 和 message ID,并以 Unicode 字符串形式返回相应的消息字符串。如果在编目中没有 message ID 和 context 条目,且配置了替补,则查找请求将被转发到替补的
pgettext()
方法。否则,返回 message ID。3.8 新版功能.
npgettext
(context, singular, plural, n)查找消息 ID 的复数形式。singular 用作消息 ID,用于在编目中查找,同时 n 用于确定使用哪种复数形式。
如果在编目中没有找到 context 对应的消息 ID,且配置了替补,则查找请求将被转发到替补的
npgettext()
方法。否则,当 n 为 1 时返回 singular,其他情况返回 plural。3.8 新版功能.
lgettext
(message)lngettext
(singular, plural, n)与
gettext()
和ngettext()
等效,但是如果没有用set_output_charset()
显式设置编码,则返回的翻译将以首选系统编码来编码字节串。警告
应避免在 Python 3 中使用这些方法。
Deprecated since version 3.8, removed in version 3.10.
Solaris 消息编目支持
Solaris 操作系统定义了自己的二进制 .mo
文件格式,但由于找不到该格式的文档,因此目前不支持该格式。
编目构造器
GNOME 用的 gettext
模块是 James Henstridge 写的版本,但该版本的 API 略有不同。它文档中的用法是:
import gettext
cat = gettext.Catalog(domain, localedir)
_ = cat.gettext
print(_('hello world'))
为了与本模块的旧版本兼容,Catalog()
函数是上述 translation()
函数的别名。
本模块与 Henstridge 的模块有一个区别:他的编目对象支持通过映射 API 进行访问,但是该特性似乎从未使用过,因此目前不支持该特性。
国际化 (I18N) 你的程序和模块
国际化 (I18N) 是指使程序可切换多种语言的操作。本地化 (L10N) 是指程序的适配能力,一旦程序被国际化,就能适配当地的语言和文化习惯。为了向 Python 程序提供不同语言的消息,需要执行以下步骤:
- 准备程序或模块,将可翻译的字符串特别标记起来
- 在已标记的文件上运行一套工具,用来生成原始消息编目
- 创建消息编目的不同语言的翻译
- 使用
gettext
模块,以便正确翻译消息字符串
为了准备代码以达成 I18N,需要巡视文件中的所有字符串。所有要翻译的字符串都应包括在 _('...')
内,以此打上标记——也就是调用 _()
函数。例如:
filename = 'mylog.txt'
message = _('writing a log message')
with open(filename, 'w') as fp:
fp.write(message)
在这个例子中,字符串 'writing a log message'
被标记为待翻译,而字符串 'mylog.txt'
和 'w'
没有被标记。
有一些工具可以将待翻译的字符串提取出来。原版的 GNU gettext 仅支持 C 或 C++ 源代码,但其扩展版 xgettext 可以扫描多种语言的代码(包括 Python),来找出标记为可翻译的字符串。Babel 是一个 Python 国际化库,其中包含一个 pybabel
脚本,用于提取并编译消息编目。François Pinard 写的称为 xpot 的程序也能完成类似的工作,可从他的 po-utils 软件包 中获取。
(Python 还包括了这些程序的纯 Python 版本,称为 pygettext.py 和 msgfmt.py,某些 Python 发行版已经安装了它们。pygettext.py 类似于 xgettext,但只能理解 Python 源代码,无法处理诸如 C 或 C++ 的其他编程语言。pygettext.py 支持的命令行界面类似于 xgettext,查看其详细用法请运行 pygettext.py --help
。msgfmt.py 与 GNU msgfmt 是二进制兼容的。有了这两个程序,可以不需要 GNU gettext 包来国际化 Python 应用程序。)
xgettext、pygettext 或类似工具生成的 .po
文件就是消息编目。它们是结构化的人类可读文件,包含源代码中所有被标记的字符串,以及这些字符串的翻译的占位符。
然后把这些 .po
文件的副本交给各个人工译者,他们为所支持的每种自然语言编写翻译。译者以 <语言名称>.po
文件的形式发送回翻译完的某个语言的版本,将该文件用 msgfmt 程序编译为机器可读的 .mo
二进制编目文件。gettext
模块使用 .mo
文件在运行时进行实际的翻译处理。
如何在代码中使用 gettext
模块取决于国际化单个模块还是整个应用程序。接下来的两节将讨论每种情况。
本地化你的模块
如果要本地化模块,则切忌进行全局性的更改,如更改内建命名空间。不应使用 GNU gettext API,而应使用基于类的 API。
假设你的模块叫做 “spam”,并且该模块的各种自然语言翻译 .mo
文件存放于 /usr/share/locale
,为 GNU gettext 格式。以下内容应放在模块顶部:
import gettext
t = gettext.translation('spam', '/usr/share/locale')
_ = t.gettext
本地化你的应用程序
如果正在本地化应用程序,可以将 _()
函数全局安装到内建命名空间中,通常在应用程序的主文件中安装。这将使某个应用程序的所有文件都能使用 _('...')
,而不必在每个文件中显式安装它。
最简单的情况,就只需将以下代码添加到应用程序的主程序文件中:
import gettext
gettext.install('myapplication')
如果需要设置语言环境目录,可以将其传递给 install()
函数:
import gettext
gettext.install('myapplication', '/usr/share/locale')
即时更改语言
如果程序需要同时支持多种语言,则可能需要创建多个翻译实例,然后在它们之间进行显式切换,如下所示:
import gettext
lang1 = gettext.translation('myapplication', languages=['en'])
lang2 = gettext.translation('myapplication', languages=['fr'])
lang3 = gettext.translation('myapplication', languages=['de'])
# start by using language1
lang1.install()
# ... time goes by, user selects language 2
lang2.install()
# ... more time goes by, user selects language 3
lang3.install()
延迟翻译
在大多数代码中,字符串会在编写位置进行翻译。但偶尔需要将字符串标记为待翻译,实际翻译却推迟到后面。一个典型的例子是:
animals = ['mollusk',
'albatross',
'rat',
'penguin',
'python', ]
# ...
for a in animals:
print(a)
此处希望将 animals
列表中的字符串标记为可翻译,但不希望在打印之前对它们进行翻译。
这是处理该情况的一种方式:
def _(message): return message
animals = [_('mollusk'),
_('albatross'),
_('rat'),
_('penguin'),
_('python'), ]
del _
# ...
for a in animals:
print(_(a))
该方法之所以可行,是因为 _()
的虚定义只是简单地返回了原本的字符串。并且该虚定义将临时覆盖内建命名空间中 _()
的定义(直到 del
命令)。即使先前在本地命名空间中已经有了 _()
的定义也请注意。
注意,第二次使用 _()
不会认为 “a” 可以传递给 gettext 程序去翻译,因为该参数不是字符串文字。
解决该问题的另一种方法是下面这个例子:
def N_(message): return message
animals = [N_('mollusk'),
N_('albatross'),
N_('rat'),
N_('penguin'),
N_('python'), ]
# ...
for a in animals:
print(_(a))
这种情况下标记可翻译的字符串使用的是函数 N_()
,该函数不会与 _()
的任何定义冲突。但是,需要教会消息提取程序去寻找用 N_()
标记的可翻译字符串。xgettext, pygettext, pybabel extract
和 xpot 都支持此功能,使用 -k
命令行开关即可。这里选择 N_()
为名称完全是任意的,它也能轻易改为 MarkThisStringForTranslation()
。
locale
—- 国际化服务
源代码: Lib/locale.py
The locale
module opens access to the POSIX locale database and functionality. The POSIX locale mechanism allows programmers to deal with certain cultural issues in an application, without requiring the programmer to know all the specifics of each country where the software is executed.
The locale
module is implemented on top of the _locale
module, which in turn uses an ANSI C locale implementation if available.
The locale
module defines the following exception and functions:
exception locale.Error
Exception raised when the locale passed to setlocale()
is not recognized.
locale.setlocale
(category, locale=None)
If locale is given and not None
, setlocale()
modifies the locale setting for the category. The available categories are listed in the data description below. locale may be a string, or an iterable of two strings (language code and encoding). If it’s an iterable, it’s converted to a locale name using the locale aliasing engine. An empty string specifies the user’s default settings. If the modification of the locale fails, the exception Error
is raised. If successful, the new locale setting is returned.
If locale is omitted or None
, the current setting for category is returned.
setlocale()
is not thread-safe on most systems. Applications typically start with a call of
import localelocale.setlocale(locale.LC_ALL, '')
This sets the locale for all categories to the user’s default setting (typically specified in the LANG
environment variable). If the locale is not changed thereafter, using multithreading should not cause problems.
locale.localeconv
()
以字典的形式返回本地约定的数据库。此字典具有以下字符串作为键:
类别 | 键 | 含意 |
---|---|---|
LC_NUMERIC |
‘decimal_point’ |
小数点字符。 |
‘grouping’ |
Sequence of numbers specifying which relative positions the ‘thousands_sep’ is expected. If the sequence is terminated with CHAR_MAX , no further grouping is performed. If the sequence terminates with a 0 , the last group size is repeatedly used. |
|
‘thousands_sep’ |
组之间使用的字符。 | |
LC_MONETARY |
‘int_curr_symbol’ |
国际货币符号。 |
‘currency_symbol’ |
当地货币符号。 | |
‘p_cs_precedes/n_cs_precedes’ |
货币符号是否在值之前(对于正值或负值)。 | |
‘p_sep_by_space/n_sep_by_space’ |
货币符号是否通过空格与值分隔(对于正值或负值)。 | |
‘mon_decimal_point’ |
用于货币金额的小数点。 | |
‘frac_digits’ |
货币值的本地格式中使用的小数位数。 | |
‘int_frac_digits’ |
货币价值的国际格式中使用的小数位数。 | |
‘mon_thousands_sep’ |
用于货币值的组分隔符。 | |
‘mon_grouping’ |
相当于 ‘grouping’ ,用于货币价值。 |
|
‘positive_sign’ |
用于标注正货币价值的符号。 | |
‘negative_sign’ |
用于注释负货币价值的符号。 | |
‘p_sign_posn/n_sign_posn’ |
符号的位置(对于正值或负值),见下文。 |
可以将所有数值设置为 CHAR_MAX
,以指示此语言环境中未指定任何值。
下面给出了 'p_sign_posn'
和 'n_sign_posn'
的可能值。
值 | 说明 |
---|---|
0 |
被括号括起来的货币和金额。 |
1 |
该标志应位于值和货币符号之前。 |
2 |
该标志应位于值和货币符号之后。 |
3 |
标志应该紧跟在值之前。 |
4 |
标志应该紧跟值项。 |
CHAR_MAX |
此语言环境中未指定任何内容。 |
The function sets temporarily the LC_CTYPE
locale to the LC_NUMERIC
locale or the LC_MONETARY
locale if locales are different and numeric or monetary strings are non-ASCII. This temporary change affects other threads.
在 3.7 版更改: The function now sets temporarily the LC_CTYPE
locale to the LC_NUMERIC
locale in some cases.
locale.nl_langinfo
(option)
Return some locale-specific information as a string. This function is not available on all systems, and the set of possible options might also vary across platforms. The possible argument values are numbers, for which symbolic constants are available in the locale module.
The nl_langinfo()
function accepts one of the following keys. Most descriptions are taken from the corresponding description in the GNU C library.
locale.CODESET
Get a string with the name of the character encoding used in the selected locale.
locale.D_T_FMT
Get a string that can be used as a format string for
time.strftime()
to represent date and time in a locale-specific way.locale.D_FMT
Get a string that can be used as a format string for
time.strftime()
to represent a date in a locale-specific way.locale.T_FMT
Get a string that can be used as a format string for
time.strftime()
to represent a time in a locale-specific way.locale.T_FMT_AMPM
Get a format string for
time.strftime()
to represent time in the am/pm format.DAY_1 ... DAY_7
Get the name of the n-th day of the week.
注解
This follows the US convention of
DAY_1
being Sunday, not the international convention (ISO 8601) that Monday is the first day of the week.ABDAY_1 ... ABDAY_7
Get the abbreviated name of the n-th day of the week.
MON_1 ... MON_12
Get the name of the n-th month.
ABMON_1 ... ABMON_12
Get the abbreviated name of the n-th month.
locale.RADIXCHAR
Get the radix character (decimal dot, decimal comma, etc.).
locale.THOUSEP
Get the separator character for thousands (groups of three digits).
locale.YESEXPR
Get a regular expression that can be used with the regex function to recognize a positive response to a yes/no question.
注解
The expression is in the syntax suitable for the
regex()
function from the C library, which might differ from the syntax used inre
.locale.NOEXPR
Get a regular expression that can be used with the regex(3) function to recognize a negative response to a yes/no question.
locale.CRNCYSTR
Get the currency symbol, preceded by “-“ if the symbol should appear before the value, “+” if the symbol should appear after the value, or “.” if the symbol should replace the radix character.
locale.ERA
Get a string that represents the era used in the current locale.
Most locales do not define this value. An example of a locale which does define this value is the Japanese one. In Japan, the traditional representation of dates includes the name of the era corresponding to the then-emperor’s reign.
Normally it should not be necessary to use this value directly. Specifying the
E
modifier in their format strings causes thetime.strftime()
function to use this information. The format of the returned string is not specified, and therefore you should not assume knowledge of it on different systems.locale.ERA_D_T_FMT
Get a format string for
time.strftime()
to represent date and time in a locale-specific era-based way.locale.ERA_D_FMT
Get a format string for
time.strftime()
to represent a date in a locale-specific era-based way.locale.ERA_T_FMT
Get a format string for
time.strftime()
to represent a time in a locale-specific era-based way.locale.ALT_DIGITS
Get a representation of up to 100 values used to represent the values 0 to 99.
locale.getdefaultlocale
([envvars])
Tries to determine the default locale settings and returns them as a tuple of the form (language code, encoding)
.
According to POSIX, a program which has not called setlocale(LC_ALL, '')
runs using the portable 'C'
locale. Calling setlocale(LC_ALL, '')
lets it use the default locale as defined by the LANG
variable. Since we do not want to interfere with the current locale setting we thus emulate the behavior in the way described above.
To maintain compatibility with other platforms, not only the LANG
variable is tested, but a list of variables given as envvars parameter. The first found to be defined will be used. envvars defaults to the search path used in GNU gettext; it must always contain the variable name 'LANG'
. The GNU gettext search path contains 'LC_ALL'
, 'LC_CTYPE'
, 'LANG'
and 'LANGUAGE'
, in that order.
Except for the code 'C'
, the language code corresponds to RFC 1766. language code and encoding may be None
if their values cannot be determined.
locale.getlocale
(category=LC_CTYPE)
Returns the current setting for the given locale category as sequence containing language code, encoding. category may be one of the LC_*
values except LC_ALL
. It defaults to LC_CTYPE
.
Except for the code 'C'
, the language code corresponds to RFC 1766. language code and encoding may be None
if their values cannot be determined.
locale.getpreferredencoding
(do_setlocale=True)
Return the locale encoding used for text data, according to user preferences. User preferences are expressed differently on different systems, and might not be available programmatically on some systems, so this function only returns a guess.
On some systems, it is necessary to invoke setlocale()
to obtain the user preferences, so this function is not thread-safe. If invoking setlocale is not necessary or desired, do_setlocale should be set to False
.
On Android or if the Python UTF-8 Mode is enabled, always return 'UTF-8'
, the locale encoding and the do_setlocale argument are ignored.
The Python preinitialization configures the LC_CTYPE locale. See also the filesystem encoding and error handler.
在 3.7 版更改: The function now always returns UTF-8
on Android or if the Python UTF-8 Mode is enabled.
locale.normalize
(localename)
Returns a normalized locale code for the given locale name. The returned locale code is formatted for use with setlocale()
. If normalization fails, the original name is returned unchanged.
If the given encoding is not known, the function defaults to the default encoding for the locale code just like setlocale()
.
locale.resetlocale
(category=LC_ALL)
Sets the locale for category to the default setting.
The default setting is determined by calling getdefaultlocale()
. category defaults to LC_ALL
.
locale.strcoll
(string1, string2)
Compares two strings according to the current LC_COLLATE
setting. As any other compare function, returns a negative, or a positive value, or 0
, depending on whether string1 collates before or after string2 or is equal to it.
locale.strxfrm
(string)
Transforms a string to one that can be used in locale-aware comparisons. For example, strxfrm(s1) < strxfrm(s2)
is equivalent to strcoll(s1, s2) < 0
. This function can be used when the same string is compared repeatedly, e.g. when collating a sequence of strings.
locale.format_string
(format, val, grouping=False, monetary=False)
Formats a number val according to the current LC_NUMERIC
setting. The format follows the conventions of the %
operator. For floating point values, the decimal point is modified if appropriate. If grouping is true, also takes the grouping into account.
If monetary is true, the conversion uses monetary thousands separator and grouping strings.
Processes formatting specifiers as in format % val
, but takes the current locale settings into account.
在 3.7 版更改: The monetary keyword parameter was added.
locale.format
(format, val, grouping=False, monetary=False)
Please note that this function works like format_string()
but will only work for exactly one %char
specifier. For example, '%f'
and '%.0f'
are both valid specifiers, but '%f KiB'
is not.
For whole format strings, use format_string()
.
3.7 版后已移除: Use format_string()
instead.
locale.currency
(val, symbol=True, grouping=False, international=False)
Formats a number val according to the current LC_MONETARY
settings.
The returned string includes the currency symbol if symbol is true, which is the default. If grouping is true (which is not the default), grouping is done with the value. If international is true (which is not the default), the international currency symbol is used.
Note that this function will not work with the ‘C’ locale, so you have to set a locale via setlocale()
first.
locale.str
(float)
Formats a floating point number using the same format as the built-in function str(float)
, but takes the decimal point into account.
locale.delocalize
(string)
Converts a string into a normalized number string, following the LC_NUMERIC
settings.
3.5 新版功能.
locale.localize
(string, grouping=False, monetary=False)
Converts a normalized number string into a formatted string following the LC_NUMERIC
settings.
3.10 新版功能.
locale.atof
(string)
Converts a string to a floating point number, following the LC_NUMERIC
settings.
locale.atoi
(string)
Converts a string to an integer, following the LC_NUMERIC
conventions.
locale.LC_CTYPE
Locale category for the character type functions. Depending on the settings of this category, the functions of module string
dealing with case change their behaviour.
locale.LC_COLLATE
Locale category for sorting strings. The functions strcoll()
and strxfrm()
of the locale
module are affected.
locale.LC_TIME
Locale category for the formatting of time. The function time.strftime()
follows these conventions.
locale.LC_MONETARY
Locale category for formatting of monetary values. The available options are available from the localeconv()
function.
locale.LC_MESSAGES
Locale category for message display. Python currently does not support application specific locale-aware messages. Messages displayed by the operating system, like those returned by os.strerror()
might be affected by this category.
locale.LC_NUMERIC
Locale category for formatting numbers. The functions format()
, atoi()
, atof()
and str()
of the locale
module are affected by that category. All other numeric formatting operations are not affected.
locale.LC_ALL
Combination of all locale settings. If this flag is used when the locale is changed, setting the locale for all categories is attempted. If that fails for any category, no category is changed at all. When the locale is retrieved using this flag, a string indicating the setting for all categories is returned. This string can be later used to restore the settings.
locale.CHAR_MAX
This is a symbolic constant used for different values returned by localeconv()
.
示例:
>>> import locale
>>> loc = locale.getlocale() # get current locale
# use German locale; name might vary with platform
>>> locale.setlocale(locale.LC_ALL, 'de_DE')
>>> locale.strcoll('f\xe4n', 'foo') # compare a string containing an umlaut
>>> locale.setlocale(locale.LC_ALL, '') # use user's preferred locale
>>> locale.setlocale(locale.LC_ALL, 'C') # use default (C) locale
>>> locale.setlocale(locale.LC_ALL, loc) # restore saved locale
Background, details, hints, tips and caveats
The C standard defines the locale as a program-wide property that may be relatively expensive to change. On top of that, some implementations are broken in such a way that frequent locale changes may cause core dumps. This makes the locale somewhat painful to use correctly.
Initially, when a program is started, the locale is the C
locale, no matter what the user’s preferred locale is. There is one exception: the LC_CTYPE
category is changed at startup to set the current locale encoding to the user’s preferred locale encoding. The program must explicitly say that it wants the user’s preferred locale settings for other categories by calling setlocale(LC_ALL, '')
.
It is generally a bad idea to call setlocale()
in some library routine, since as a side effect it affects the entire program. Saving and restoring it is almost as bad: it is expensive and affects other threads that happen to run before the settings have been restored.
If, when coding a module for general use, you need a locale independent version of an operation that is affected by the locale (such as certain formats used with time.strftime()
), you will have to find a way to do it without using the standard library routine. Even better is convincing yourself that using locale settings is okay. Only as a last resort should you document that your module is not compatible with non-C
locale settings.
The only way to perform numeric operations according to the locale is to use the special functions defined by this module: atof()
, atoi()
, format()
, str()
.
There is no way to perform case conversions and character classifications according to the locale. For (Unicode) text strings these are done according to the character value only, while for byte strings, the conversions and classifications are done according to the ASCII value of the byte, and bytes whose high bit is set (i.e., non-ASCII bytes) are never converted or considered part of a character class such as letter or whitespace.
For extension writers and programs that embed Python
Extension modules should never call setlocale()
, except to find out what the current locale is. But since the return value can only be used portably to restore it, that is not very useful (except perhaps to find out whether or not the locale is C
).
When Python code uses the locale
module to change the locale, this also affects the embedding application. If the embedding application doesn’t want this to happen, it should remove the _locale
extension module (which does all the work) from the table of built-in modules in the config.c
file, and make sure that the _locale
module is not accessible as a shared library.
Access to message catalogs
locale.gettext
(msg)
locale.dgettext
(domain, msg)
locale.dcgettext
(domain, msg, category)
locale.textdomain
(domain)
locale.bindtextdomain
(domain, dir)
The locale module exposes the C library’s gettext interface on systems that provide this interface. It consists of the functions gettext()
, dgettext()
, dcgettext()
, textdomain()
, bindtextdomain()
, and bind_textdomain_codeset()
. These are similar to the same functions in the gettext
module, but use the C library’s binary format for message catalogs, and the C library’s search algorithms for locating message catalogs.
Python applications should normally find no need to invoke these functions, and should use gettext
instead. A known exception to this rule are applications that link with additional C libraries which internally invoke gettext()
or dcgettext()
. For these applications, it may be necessary to bind the text domain, so that the libraries can properly locate their message catalogs.
程序框架
本章描述的完整模块列表如下:
turtle
—- 海龟绘图- 概述
- 可用的 Turtle 和 Screen 方法概览
- Turtle 方法
- TurtleScreen/Screen 方法
- RawTurtle/Turtle 方法和对应函数
- 海龟动作
- 获取海龟的状态
- 度量单位设置
- 画笔控制
- 绘图状态
- 颜色控制
- 填充
- 更多绘图控制
- 海龟状态
- 可见性
- 外观
- 使用事件
- 特殊海龟方法
- 复合形状
- TurtleScreen/Screen 方法及对应函数
- 窗口控制
- 动画控制
- 使用屏幕事件
- 输入方法
- 设置与特殊方法
- Screen 专有方法, 而非继承自 TurtleScreen
- 公共类
- 帮助与配置
- 如何使用帮助
- 文档字符串翻译为不同的语言
- 如何配置 Screen 和 Turtle
turtledemo
—- 演示脚本集- Python 2.6 之后的变化
- Python 3.0 之后的变化
cmd
—- 支持面向行的命令解释器- Cmd 对象
- Cmd 例子
shlex
—— 简单的词法分析- shlex 对象
- 解析规则
- 改进的 shell 兼容性
turtle
—- 海龟绘图
源码: Lib/turtle.py
概述
海龟绘图很适合用来引导孩子学习编程。 最初来自于 Wally Feurzeig, Seymour Papert 和 Cynthia Solomon 于 1967 年所创造的 Logo 编程语言。
请想象绘图区有一只机器海龟,起始位置在 x-y 平面的 (0, 0) 点。先执行 import turtle
,再执行 turtle.forward(15)
,它将(在屏幕上)朝所面对的 x 轴正方向前进 15 像素,随着它的移动画出一条线段。再执行 turtle.right(25)
,它将原地右转 25 度。
Turtle star
使用海龟绘图可以编写重复执行简单动作的程序画出精细复杂的形状。
from turtle import *
color('red', 'yellow')
begin_fill()
while True:
forward(200)
left(170)
if abs(pos()) < 1:
break
end_fill()
done()
通过组合使用此类命令,可以轻松地绘制出精美的形状和图案。
turtle
模块是基于 Python 标准发行版 2.5 以来的同名模块重新编写并进行了功能扩展。
新模块尽量保持了原模块的特点,并且(几乎)100%与其兼容。这就意味着初学编程者能够以交互方式使用模块的所有命令、类和方法——运行 IDLE 时注意加 -n
参数。
turtle 模块提供面向对象和面向过程两种形式的海龟绘图基本组件。由于它使用 tkinter
实现基本图形界面,因此需要安装了 Tk 支持的 Python 版本。
面向对象的接口主要使用“2+2”个类:
TurtleScreen
类定义图形窗口作为绘图海龟的运动场。它的构造器需要一个tkinter.Canvas
或ScrolledCanvas
作为参数。应在turtle
作为某个程序的一部分的时候使用。Screen()
函数返回一个TurtleScreen
子类的单例对象。此函数应在turtle
作为独立绘图工具时使用。作为一个单例对象,其所属的类是不可被继承的。TurtleScreen/Screen 的所有方法还存在对应的函数,即作为面向过程的接口组成部分。
RawTurtle
(别名:RawPen
) 类定义海龟对象在TurtleScreen
上绘图。它的构造器需要一个 Canvas, ScrolledCanvas 或 TurtleScreen 作为参数,以指定 RawTurtle 对象在哪里绘图。从 RawTurtle 派生出子类
Turtle
(别名:Pen
),该类对象在Screen
实例上绘图,如果实例不存在则会自动创建。RawTurtle/Turtle 的所有方法也存在对应的函数,即作为面向过程的接口组成部分。
过程式接口提供与 Screen
和 Turtle
类的方法相对应的函数。函数名与对应的方法名相同。当 Screen 类的方法对应函数被调用时会自动创建一个 Screen 对象。当 Turtle 类的方法对应函数被调用时会自动创建一个 (匿名的) Turtle 对象。
如果屏幕上需要有多个海龟,就必须使用面向对象的接口。
shlex
—— 简单的词法分析
源代码: Lib/shlex.py
shlex
类可用于编写类似 Unix shell 的简单词法分析程序。通常可用于编写“迷你语言”(如 Python 应用程序的运行控制文件)或解析带引号的字符串。
shlex
模块中定义了以下函数:
shlex.split
(s, comments=False, posix=True)
用类似 shell 的语法拆分字符串 s。如果 comments 为 False
(默认值),则不会解析给定字符串中的注释 (commenters
属性的 shlex
实例设为空字符串)。 本函数默认工作于 POSIX 模式下,但若 posix 参数为 False,则采用非 POSIX 模式。
注解
Since the split()
function instantiates a shlex
instance, passing None
for s will read the string to split from standard input.
3.9 版后已移除: 在以后的 Python 版本中,给 s 传入 None
将触发异常。
shlex.join
(split_command)
将列表 split_command 中的词法单元(token)串联起来,返回一个字符串。本函数是 split()
的逆运算。
>>> from shlex import join
>>> print(join(['echo', '-n', 'Multiple words']))
echo -n 'Multiple words'
为防止注入漏洞,返回值是经过 shell 转义的。
3.8 新版功能.
shlex.quote
(s)
返回经过 shell 转义的字符串 s 。返回值为字符串,可以安全地用作 shell 命令行中的词法单元,可用于不能使用列表的场合。
警告
shlex
模块 仅适用于 Unix shell。
在不兼容 POSIX 的 shell 或其他操作系统(如Windows)的shell上,并不保证 quote()
函数能够正常使用。在这种 shell 中执行用本模块包装过的命令,有可能会存在命令注入漏洞。
请考虑采用命令参数以列表形式给出的函数,比如带了 shell=False
参数的 subprocess.run()
。
以下用法是不安全的:
>>> filename = 'somefile; rm -rf ~'
>>> command = 'ls -l {}'.format(filename)
>>> print(command) # executed by a shell: boom!
ls -l somefile; rm -rf ~
用 quote()
可以堵住这种安全漏洞:
>>> from shlex import quote
>>> command = 'ls -l {}'.format(quote(filename))
>>> print(command)
ls -l 'somefile; rm -rf ~'
>>> remote_command = 'ssh home {}'.format(quote(command))
>>> print(remote_command)
ssh home 'ls -l '"'"'somefile; rm -rf ~'"'"''
这种包装方式兼容于 UNIX shell 和 split()
。
>>> from shlex import split
>>> remote_command = split(remote_command)
>>> remote_command
['ssh', 'home', "ls -l 'somefile; rm -rf ~'"]
>>> command = split(remote_command[-1])
>>> command
['ls', '-l', 'somefile; rm -rf ~']
3.3 新版功能.
shlex
模块中定义了以下类:
class shlex.shlex
(instream=None, infile=None, posix=False, punctuation_chars=False)
shlex
及其子类的实例是一种词义分析器对象。 利用初始化参数可指定从哪里读取字符。 初始化参数必须是具备 read()
和 readline()
方法的文件/流对象,或者是一个字符串。 如果没有给出初始化参数,则会从 sys.stdin
获取输入。 第二个可选参数是个文件名字符串,用于设置 infile
属性的初始值。 如果 instream 参数被省略或等于 sys.stdin
,则第二个参数默认为 “stdin”。 posix 参数定义了操作的模式:若 posix 不为真值(默认),则 shlex
实例将工作于兼容模式。 若运行于 POSIX 模式下,则 shlex
会尽可能地应用 POSIX shell 解析规则。 punctuation_chars 参数提供了一种使行为更接近于真正的 shell 解析的方式。 该参数可接受多种值:默认值、False
、保持 Python 3.5 及更早版本的行为。 如果设为 True
,则会改变对字符 ();<>|&
的解析方式:这些字符将作为独立的词法单元被返回(视作标点符号)。 如果设为非空字符串,则这些字符将被用作标点符号。 出现在 punctuation_chars 中的 wordchars
属性中的任何字符都会从 wordchars
中被删除。 punctuation_chars 只能在创建 shlex
实例时设置,以后不能再作修改。
在 3.6 版更改: 加入 punctuation_chars 参数。
配置文件解析器,类似于 Windows 的 .ini
文件。
shlex 对象
shlex
实例具备以下方法:
shlex.get_token
()
返回一个词法单元。如果所有单词已用 push_token()
堆叠在一起了,则从堆栈中弹出一个词法单元。否则就从输入流中读取一个。如果读取时遇到文件结束符,则会返回 eof
(在非 POSIX 模式下为空字符串 ‘’
,在 POSIX 模式下为 ``None
)。
shlex.push_token
(str)
将参数值压入词法单元堆栈。
shlex.read_token
()
读取一个原始词法单元。忽略堆栈,且不解释源请求。(通常没什么用,只是为了完整起见。)
shlex.sourcehook
(filename)
当 shlex
检测到源请求,以下词法单元可作为参数,并应返回一个由文件名和打开的文件对象组成的元组。
通常本方法会先移除参数中的引号。如果结果为绝对路径名,或者之前没有有效的源请求,或者之前的源请求是一个流对象(比如 sys.stdin
),那么结果将不做处理。否则,如果结果是相对路径名,那么前面将会加上目录部分,目录名来自于源堆栈中前一个文件名(类似于 C 预处理器对 #include "file.h"
的处理方式)。
结果被视为一个文件名,并作为元组的第一部分返回,元组的第二部分以此为基础调用 open()
获得。(注意:这与实例初始化过程中的参数顺序相反!)
此钩子函数是公开的,可用于实现路径搜索、添加文件扩展名或黑入其他命名空间。没有对应的“关闭”钩子函数,但 shlex 实例在返回 EOF 时会调用源输入流的 close()
方法。
若要更明确地控制源堆栈,请采用 push_source()
和 pop_source()
方法。
shlex.push_source
(newstream, newfile=None)
将输入源流压入输入堆栈。如果指定了文件名参数,以后错误信息中将会用到。sourcehook()
内部同样使用了本方法。
shlex.pop_source
()
从输入堆栈中弹出最后一条输入源。当遇到输入流的 EOF 时,内部也使用同一方法。
shlex.error_leader
(infile=None, lineno=None)
本方法生成一条错误信息的首部,以 Unix C 编译器错误标签的形式;格式为‘“%s”, line %d: ‘`,其中
%s被替换为当前源文件的名称,
%d` 被替换为当前输入行号(可用可选参数覆盖)。
这是个快捷函数,旨在鼓励 shlex
用户以标准的、可解析的格式生成错误信息,以便 Emacs 和其他 Unix 工具理解。
shlex
子类的实例有一些公共实例变量,这些变量可以控制词义分析,也可用于调试。
shlex.commenters
将被视为注释起始字符串。从注释起始字符串到行尾的所有字符都将被忽略。默认情况下只包括 '#'
。
shlex.wordchars
可连成多字符词法单元的字符串。默认包含所有 ASCII 字母数字和下划线。在 POSIX 模式下,Latin-1 字符集的重音字符也被包括在内。如果 punctuation_chars
不为空,则可出现在文件名规范和命令行参数中的 ~-./*?=
字符也将包含在内,任何 punctuation_chars
中的字符将从 wordchars
中移除。如果 whitespace_split
设为 True
,则本规则无效。
shlex.whitespace
将被视为空白符并跳过的字符。空白符是词法单元的边界。默认包含空格、制表符、换行符和回车符。
shlex.escape
将视为转义字符。仅适用于 POSIX 模式,默认只包含 '\'
。
shlex.quotes
将视为引号的字符。词法单元中的字符将会累至再次遇到同样的引号(因此,不同的引号会像在 shell 中一样相互包含。)默认包含 ASCII 单引号和双引号。
shlex.escapedquotes
quotes
中的字符将会解析 escape
定义的转义字符。这只在 POSIX 模式下使用,默认只包含 '"'
。
shlex.whitespace_split
若为 True
,则只根据空白符拆分词法单元。这很有用,比如用 shlex
解析命令行,用类似 shell 参数的方式读取各个词法单元。当与 punctuation_chars
一起使用时,将根据空白符和这些字符拆分词法单元。
在 3.8 版更改: punctuation_chars
属性已与 whitespace_split
属性兼容。
shlex.infile
当前输入的文件名,可能是在类实例化时设置的,或者是由后来的源请求堆栈生成的。在构建错误信息时可能会用到本属性。
shlex.instream
shlex
实例正从中读取字符的输入流。
shlex.source
本属性默认值为 None
。 如果给定一个字符串,则会识别为包含请求,类似于各种 shell 中的 source
关键字。 也就是说,紧随其后的词法单元将作为文件名打开,作为输入流,直至遇到 EOF 后调用流的 close()
方法,然后原输入流仍变回输入源。Source 请求可以在词义堆栈中嵌套任意深度。
shlex.debug
如果本属性为大于 1
的数字,则 shlex
实例会把动作进度详细地输出出来。若需用到本属性,可阅读源代码来了解细节。
shlex.lineno
源的行数(到目前为止读到的换行符数量加 1)。
shlex.token
词法单元的缓冲区。在捕获异常时可能会用到。
shlex.eof
用于确定文件结束的词法单元。在非 POSIX 模式下,将设为空字符串 ''
,在 POSIX 模式下被设为 None
。
shlex.punctuation_chars
只读属性。表示应视作标点符号的字符。标点符号将作为单个词法单元返回。然而,请注意不会进行语义有效性检查:比如 “>>>” 可能会作为一个词法单元返回,虽然 shell 可能无法识别。
3.6 新版功能.
解析规则
在非 POSIX 模式下时,shlex
会试图遵守以下规则:
- 不识别单词中的引号(
Do"Not"Separate
解析为一个单词Do"Not"Separate
); - 不识别转义字符;
- 引号包裹的字符保留字面意思;
- 成对的引号会将单词分离(
"Do"Separate
解析为"Do"
和Separate
); - 如果
whitespace_split
为False
,则未声明为单词字符、空白或引号的字符将作为单字符的词法单元返回。若为True
, 则shlex
只根据空白符拆分单词。 - EOF 用空字符串(
''
)表示; - 空字符串无法解析,即便是加了引号。
在 POSIX 模式时,shlex
将尝试遵守以下解析规则:
- 引号会被剔除,且不会拆分单词(
"Do"Not"Separate"
将解析为单个单词DoNotSeparate
); - 未加引号包裹的转义字符(如
'\'
)保留后一个字符的字面意思; - 引号中的字符不属于
escapedquotes
(例如,"'"
),则保留引号中所有字符的字面值; - 若引号包裹的字符属于
escapedquotes
(例如'"'
),则保留引号中所有字符的字面意思,属于escape
中的字符除外。仅当后跟后半个引号或转义字符本身时,转义字符才保留其特殊含义。否则,转义字符将视作普通字符; - EOF 用
None
表示; - 允许出现引号包裹的空字符串(
''
)。
改进的 shell 兼容性
3.6 新版功能.
shlex
类提供了与常见 Unix shell(如 bash
、dash
和sh
)的解析兼容性。为了充分利用这种兼容性,请在构造函数中设定 punctuation_chars
参数。该参数默认为 False
,维持 3.6 以下版本的行为。如果设为 True
,则会改变对 ();<>|&
字符的解析方式:这些字符都将视为单个的词法单元返回。虽然不算是完整的 shell 解析程序(考虑到 shell 的多样性,超出了标准库的范围),但确实能比其他方式更容易进行命令行的处理。以下代码段演示了两者的差异:
>>> import shlex
>>> text = "a && b; c && d || e; f >'abc'; (def \"ghi\")"
>>> s = shlex.shlex(text, posix=True)
>>> s.whitespace_split = True
>>> list(s)
['a', '&&', 'b;', 'c', '&&', 'd', '||', 'e;', 'f', '>abc;', '(def', 'ghi)']
>>> s = shlex.shlex(text, posix=True, punctuation_chars=True)
>>> s.whitespace_split = True
>>> list(s)
['a', '&&', 'b', ';', 'c', '&&', 'd', '||', 'e', ';', 'f', '>', 'abc', ';',
'(', 'def', 'ghi', ')']
当然,返回的词法单元对 shell 无效,需要对返回的词法单元自行进行错误检查。
punctuation_chars 参数可以不传入 True
,而是传入包含特定字符的字符串,用于确定由哪些字符构成标点符号。例如:
>>> import shlex
>>> s = shlex.shlex("a && b || c", punctuation_chars="|")
>>> list(s)
['a', '&', '&', 'b', '||', 'c']
注解
如果指定了 punctuation_chars
,则 wordchars
属性的参数会是 ~-./*?=
。因为这些字符可以出现在文件名(包括通配符)和命令行参数中(如 --color=auto
)。因此:
>>> import shlex
>>> s = shlex.shlex('~/a && b-c --color=auto || d *.py?',
... punctuation_chars=True)
>>> list(s)
['~/a', '&&', 'b-c', '--color=auto', '||', 'd', '*.py?']
不过为了尽可能接近于 shell ,建议在使用 punctuation_chars
时始终使用 posix
和 whitespace_split
,这将完全否定 wordchars
。
为了达到最佳效果,punctuation_chars
应与 posix=True
一起设置。(注意 posix=False
是 shlex
的默认设置)。
cmd
—- 支持面向行的命令解释器
源代码: Lib/cmd.py
Cmd
类提供简单框架用于编写面向行的命令解释器。 这些通常对测试工具,管理工具和原型有用,这些工具随后将被包含在更复杂的接口中。
class cmd.Cmd
(completekey=’tab’, stdin=None, stdout=None)
一个 Cmd
实例或子类实例是面向行的解释器框架结构。 实例化 Cmd
本身是没有充分理由的, 它作为自定义解释器类的超类是非常有用的为了继承 Cmd
的方法并且封装动作方法。
可选参数 completekey 是完成键的 readline
名称;默认是 Tab 。如果 completekey 不是 None
并且 readline
是可用的, 命令完成会自动完成。
可选参数 stdin 和 stdout 指定了Cmd实例或子类实例将用于输入和输出的输入和输出文件对象。如果没有指定,他们将默认为 sys.stdin
和 sys.stdout
。
如果你想要使用一个给定的 stdin ,确保将实例的 use_rawinput
属性设置为 False
,否则 stdin 将被忽略。
Cmd 对象
Cmd
实例有下列方法:
Cmd.cmdloop
(intro=None)
反复发出提示,接受输入,从收到的输入中解析出一个初始前缀,并分派给操作方法,将其余的行作为参数传递给它们。
可选参数是在第一个提示之前发布的横幅或介绍字符串(这将覆盖 intro
类属性)。
如果 readline
继承模块被加载,输入将自动继承类似 bash的历史列表编辑(例如, Control-P 滚动回到最后一个命令, Control-N 转到下一个命令,以 Control-F 非破坏性的方式向右 Control-B 移动光标,破坏性地等)。
输入的文件结束符被作为字符串传回 'EOF'
。
解释器实例将会识别命令名称 foo
当且仅当它有方法 do_foo()
。有一个特殊情况,分派始于字符 '?'
的行到方法 do_help()
。另一种特殊情况,分派始于字符 '!'
的行到方法 do_shell()
(如果定义了这个方法)
这个方法将返回当 postcmd()
方法返回一个真值 。参数 stop 到 postcmd()
是命令对应的返回值 do_*()
的方法。
如果激活了完成,全部命令将会自动完成,并且通过调用 complete_foo()
参数 text , line, begidx ,和 endidx 完成全部命令参数。 text 是我们试图匹配的字符串前缀,所有返回的匹配项必须以它为开头。 line 是删除了前导空格的当前的输入行, begidx 和 endidx 是前缀文本的开始和结束索引。,可以用于根据参数位置提供不同的完成。
所有 Cmd
的子类继承一个预定义 do_help()
。 这个方法使用参数 'bar'
调用, 调用对应的方法 help_bar()
,如果不存在,打印 do_bar()
的文档字符串,如果可用。没有参数的情况下, do_help()
方法会列出所有可用的帮助主题 (即所有具有相应的 help_*()
方法或命令的 文档字符串),也会列举所有未被记录的命令。
Cmd.onecmd
(str)
解释该参数,就好像它是为响应提示而键入的一样。 这可能会被覆盖,但通常不应该被覆盖; 用于执行有用的挂钩。 返回值是一个标志,指示解释器对命令的解释是否应该停止。 如果命令 str 有一个 do_*()
方法,则返回该方法的返回值,否则返回 default()
方法的返回值。
Cmd.emptyline
()
在响应提示输入空行时调用的方法。如果此方法未被覆盖,则重复输入的最后一个非空命令。
Cmd.default
(line)
当命令前缀不能被识别的时候在输入行调用的方法。如果此方法未被覆盖,它将输出一个错误信息并返回。
Cmd.completedefault
(text, line, begidx, endidx)
当没有特定于命令的 complete_*()
方法可用时,调用此方法完成输入行。默认情况下,它返回一个空列表。
Cmd.precmd
(line)
钩方法在命令行 line 被解释之前执行,但是在输入提示被生成和发出后。这个方法是一个在 Cmd
中的存根;它的存在是为了被子类覆盖。返回值被用作 onecmd()
方法执行的命令; precmd()
的实现或许会重写命令或者简单的返回 line 不变。
Cmd.postcmd
(stop, line)
钩方法只在命令调度完成后执行。这个方法是一个在 Cmd
中的存根;它的存在是为了子类被覆盖。 line 是被执行的命令行, stop 是一个表示在调用 postcmd()
之后是否终止执行的标志;这将作为 onecmd()
方法的返回值。这个方法的返回值被用作与 stop 相关联的内部标志的新值;返回 false 将导致解释继续。
Cmd.preloop
()
钩方法当 cmdloop()
被调用时执行一次。方法是一个在 Cmd
中的存根;它的存在是为了被子类覆盖。
Cmd.postloop
()
钩方法在 cmdloop()
即将返回时执行一次。这个方法是一个在 Cmd
中的存根;它的存在是为了被子类覆盖。
Instances of Cmd
subclasses have some public instance variables:
Cmd.prompt
发出提示以请求输入。
Cmd.identchars
接受命令前缀的字符串。
Cmd.lastcmd
看到最后一个非空命令前缀。
Cmd.cmdqueue
排队的输入行列表。当需要新的输入时,在 cmdloop()
中检查 cmdqueue 列表;如果它不是空的,它的元素将被按顺序处理,就像在提示符处输入一样。
Cmd.intro
要作为简介或横幅发出的字符串。 可以通过给 cmdloop()
方法一个参数来覆盖它。
Cmd.doc_header
如果帮助输出具有记录命令的段落,则发出头文件。
Cmd.misc_header
如果帮助输出其他帮助主题的部分(即与 do_*()
方法没有关联的 help_*()
方法),则发出头文件。
Cmd.undoc_header
如果帮助输出未被记录命令的部分(即与 help_*()
方法没有关联的 do_*()
方法),则发出头文件。
Cmd.ruler
用于在帮助信息标题的下方绘制分隔符的字符,如果为空,则不绘制标尺线。这个字符默认是 '='
。
Cmd.use_rawinput
这是一个标志,默认为 true 。如果为 true ,, cmdloop()
使用 input()
先是提示并且阅读下一个命令;如果为 false , sys.stdout.write()
和 sys.stdin.readline()
被使用。(这意味着解释器将会自动支持类似于 Emacs的行编辑和命令历史记录按键操作,通过导入 readline
在支持它的系统上。)
Cmd 例子
The cmd
module is mainly useful for building custom shells that let a user work with a program interactively.
这部分提供了一个简单的例子来介绍如何使用一部分在 turtle
模块中的命令构建一个 shell 。
基础的 turtle 命令比如 forward()
被添加进一个 Cmd
子类,方法名为 do_forward()
。参数被转换成数字并且分发至 turtle 模块中。 docstring 是 shell 提供的帮助实用程序。
例子也包含使用 precmd()
方法实现基础的记录和回放的功能,这个方法负责将输入转换为小写并且将命令写入文件。 do_playback()
方法读取文件并添加记录命令至 cmdqueue
用于即时回放:
import cmd, sys
from turtle import *
class TurtleShell(cmd.Cmd):
intro = 'Welcome to the turtle shell. Type help or ? to list commands.\n'
prompt = '(turtle) '
file = None
# ----- basic turtle commands -----
def do_forward(self, arg):
'Move the turtle forward by the specified distance: FORWARD 10'
forward(*parse(arg))
def do_right(self, arg):
'Turn turtle right by given number of degrees: RIGHT 20'
right(*parse(arg))
def do_left(self, arg):
'Turn turtle left by given number of degrees: LEFT 90'
left(*parse(arg))
def do_goto(self, arg):
'Move turtle to an absolute position with changing orientation. GOTO 100 200'
goto(*parse(arg))
def do_home(self, arg):
'Return turtle to the home position: HOME'
home()
def do_circle(self, arg):
'Draw circle with given radius an options extent and steps: CIRCLE 50'
circle(*parse(arg))
def do_position(self, arg):
'Print the current turtle position: POSITION'
print('Current position is %d %d\n' % position())
def do_heading(self, arg):
'Print the current turtle heading in degrees: HEADING'
print('Current heading is %d\n' % (heading(),))
def do_color(self, arg):
'Set the color: COLOR BLUE'
color(arg.lower())
def do_undo(self, arg):
'Undo (repeatedly) the last turtle action(s): UNDO'
def do_reset(self, arg):
'Clear the screen and return turtle to center: RESET'
reset()
def do_bye(self, arg):
'Stop recording, close the turtle window, and exit: BYE'
print('Thank you for using Turtle')
self.close()
bye()
return True
# ----- record and playback -----
def do_record(self, arg):
'Save future commands to filename: RECORD rose.cmd'
self.file = open(arg, 'w')
def do_playback(self, arg):
'Playback commands from a file: PLAYBACK rose.cmd'
self.close()
with open(arg) as f:
self.cmdqueue.extend(f.read().splitlines())
def precmd(self, line):
line = line.lower()
if self.file and 'playback' not in line:
print(line, file=self.file)
return line
def close(self):
if self.file:
self.file.close()
self.file = None
def parse(arg):
'Convert a series of zero or more numbers to an argument tuple'
return tuple(map(int, arg.split()))
if __name__ == '__main__':
TurtleShell().cmdloop()
这是一个示例会话,其中 turtle shell 显示帮助功能,使用空行重复命令,以及简单的记录和回放功能:
Welcome to the turtle shell. Type help or ? to list commands.
(turtle) ?
Documented commands (type help <topic>):
========================================
bye color goto home playback record right
circle forward heading left position reset undo
(turtle) help forward
Move the turtle forward by the specified distance: FORWARD 10
(turtle) record spiral.cmd
(turtle) position
Current position is 0 0
(turtle) heading
Current heading is 0
(turtle) reset
(turtle) circle 20
(turtle) right 30
(turtle) circle 40
(turtle) right 30
(turtle) circle 60
(turtle) right 30
(turtle) circle 80
(turtle) right 30
(turtle) circle 100
(turtle) right 30
(turtle) circle 120
(turtle) right 30
(turtle) circle 120
(turtle) heading
Current heading is 180
(turtle) forward 100
(turtle)
(turtle) right 90
(turtle) forward 100
(turtle)
(turtle) right 90
(turtle) forward 400
(turtle) right 90
(turtle) forward 500
(turtle) right 90
(turtle) forward 400
(turtle) right 90
(turtle) forward 300
(turtle) playback spiral.cmd
Current position is 0 0
Current heading is 0
Current heading is 180
(turtle) bye
Thank you for using Turtle
Tk图形用户界面(GUI)
Tcl/Tk集成到Python中已经有一些年头了。Python程序员可以通过 tkinter
包和它的扩展, tkinter.tix
模块和 tkinter.ttk
模块,来使用这套鲁棒的、平台无关的窗口工具集。
tkinter
包是使用面向对象方式对 Tcl/Tk 进行的一层薄包装。 使用 tkinter
,你不需要写 Tcl 代码,但你将需要参阅 Tk 文档,有时还需要参阅 Tcl 文档。 tkinter
是一组包装器,它将 Tk 的可视化部件实现为相应的 Python 类。
tkinter
的主要特点是速度很快,并且通常直接附带在 Python 中。 虽然它的官方文档做得不好,但还是有许多可用的资源,包括:在线参考、教程、入门书等等。 tkinter
还有众所周知的较过时的外观界面,这在 Tk 8.5 中已得到很大改进。 无论如何,你还可以考虑许多其他的 GUI 库。 Python wiki 例出了一些替代性的 GUI 框架和工具。
tkinter
— Tcl/Tk的Python接口- Architecture
- Tkinter 模块
- Tkinter Life Preserver
- Threading model
- Handy Reference
- File Handlers
tkinter.colorchooser
— 颜色选择对话框tkinter.font
— Tkinter 字体封装- Tkinter 对话框
tkinter.simpledialog
— 标准 Tkinter 输入对话框tkinter.filedialog
— 文件选择对话框.tkinter.commondialog
— 对话窗口模板
tkinter.messagebox
— Tkinter 消息提示tkinter.scrolledtext
— 滚动文字控件tkinter.dnd
— 拖放操作支持tkinter.ttk
— Tk主题部件tkinter.tix
— TK扩展包- IDLE
- 目录
- 编辑和导航
- 启动和代码执行
- 帮助和偏好
开发工具
本章中描述的各模块可帮你编写 Python 程序。例如,pydoc
模块接受一个模块并根据该模块的内容来生成文档。doctest
和 unittest
这两个模块包含了用于编写单元测试的框架,并可用于自动测试所编写的代码,验证预期的输出是否产生。2to3 程序能够将 Python 2.x 源代码翻译成有效的 Python 3.x 源代码。
本章中描述的模块列表是:
typing
—- 类型提示支持- 类型别名
- NewType
- 可调对象(Callable)
- 泛型(Generic)
- 用户定义的泛型类型
Any
类型- 名义子类型 vs 结构子类型
- 模块内容
- 特殊类型原语
- 特殊类型
- 特殊形式
- 构建泛型类型
- 其他特殊指令
- 泛型具象容器
- 对应的内置类型
collections
对应类型- 其他具象类型
- 抽象基类
collections.abc
对应的容器collections.abc
对应的其他类型- 异步编程
- 上下文管理器类型
- 协议
- 函数与装饰器
- 内省辅助器
- 常量
- 特殊类型原语
pydoc
—- 文档生成器和在线帮助系统- Python Development Mode
- Effects of the Python Development Mode
- ResourceWarning Example
- Bad file descriptor error example
doctest
—- 测试交互性的Python示例- 简单用法:检查Docstrings中的示例
- Simple Usage: Checking Examples in a Text File
- How It Works
- Which Docstrings Are Examined?
- How are Docstring Examples Recognized?
- What’s the Execution Context?
- What About Exceptions?
- Option Flags
- Directives
- 警告
- Basic API
- Unittest API
- Advanced API
- DocTest 对象
- Example Objects
- DocTestFinder 对象
- DocTestParser 对象
- DocTestRunner 对象
- OutputChecker 对象
- 调试
- Soapbox
unittest
—- 单元测试框架- 基本实例
- 命令行接口
- 命令行选项
- 探索性测试
- 组织你的测试代码
- 复用已有的测试代码
- 跳过测试与预计的失败
- Distinguishing test iterations using subtests
- 类与函数
- 测试用例
- Deprecated aliases
- Grouping tests
- Loading and running tests
- load_tests Protocol
- 测试用例
- Class and Module Fixtures
- setUpClass and tearDownClass
- setUpModule and tearDownModule
- 信号处理
unittest.mock
—- 模拟对象库- 快速上手
- Mock 类
- Calling
- Deleting Attributes
- Mock names and the name attribute
- Attaching Mocks as Attributes
- The patchers
- patch
- patch.object
- patch.dict
- patch.multiple
- patch methods: start and stop
- patch builtins
- TEST_PREFIX
- Nesting Patch Decorators
- Where to patch
- Patching Descriptors and Proxy Objects
- MagicMock and magic method support
- Mocking Magic Methods
- Magic Mock
- Helpers
- sentinel
- DEFAULT
- call
- create_autospec
- ANY
- FILTER_DIR
- mock_open
- Autospeccing
- Sealing mocks
unittest.mock
上手指南- 使用 mock
- 模拟方法调用
- 对象上的方法调用的 mock
- Mocking Classes
- Naming your mocks
- Tracking all Calls
- Setting Return Values and Attributes
- Raising exceptions with mocks
- Side effect functions and iterables
- Mocking asynchronous iterators
- Mocking asynchronous context manager
- Creating a Mock from an Existing Object
- Patch Decorators
- Further Examples
- Mocking chained calls
- Partial mocking
- Mocking a Generator Method
- Applying the same patch to every test method
- Mocking Unbound Methods
- Checking multiple calls with mock
- Coping with mutable arguments
- Nesting Patches
- Mocking a dictionary with MagicMock
- Mock subclasses and their attributes
- Mocking imports with patch.dict
- Tracking order of calls and less verbose call assertions
- More complex argument matching
- 使用 mock
- 2to3 - 自动将 Python 2 代码转为 Python 3 代码
- 使用 2to3
- 修复器
lib2to3
—— 2to3 支持库
test
—- Python回归测试包- Writing Unit Tests for the
test
package - Running tests using the command-line interface
- Writing Unit Tests for the
test.support
—- Utilities for the Python test suitetest.support.socket_helper
—- Utilities for socket teststest.support.script_helper
—- Utilities for the Python execution teststest.support.bytecode_helper
—- Support tools for testing correct bytecode generationtest.support.threading_helper
—- Utilities for threading teststest.support.os_helper
—- Utilities for os teststest.support.import_helper
—- Utilities for import teststest.support.warnings_helper
—- Utilities for warnings tests
typing
—- 类型提示支持
3.5 新版功能.
源码: Lib/typing.py
注解
Python 运行时不强制执行函数和变量类型注解,但这些注解可用于类型检查器、IDE、静态检查器等第三方工具。
This module provides runtime support for type hints as specified by PEP 484, PEP 526, PEP 544, PEP 586, PEP 589, PEP 591, PEP 612 and PEP 613. The most fundamental support consists of the types Any
, Union
, Tuple
, Callable
, TypeVar
, and Generic
. For full specification please see PEP 484. For a simplified introduction to type hints see PEP 483.
下面的函数接收与返回的都是字符串,注解方式如下:
def greeting(name: str) -> str:
return 'Hello ' + name
greeting
函数中,参数 name
的类型是 str
,返回类型也是 str
。子类型也可以当作参数。
类型别名
把类型赋给别名,就可以定义类型别名。本例中,Vector
和 list[float]
相同,可互换:
Vector = list[float]
def scale(scalar: float, vector: Vector) -> Vector:
return [scalar * num for num in vector]
# typechecks; a list of floats qualifies as a Vector.
new_vector = scale(2.0, [1.0, -4.2, 5.4])
类型别名适用于简化复杂的类型签名。例如:
from collections.abc import Sequence
ConnectionOptions = dict[str, str]
Address = tuple[str, int]
Server = tuple[Address, ConnectionOptions]
def broadcast_message(message: str, servers: Sequence[Server]) -> None:
...
# The static type checker will treat the previous type signature as
# being exactly equivalent to this one.
def broadcast_message(
message: str,
servers: Sequence[tuple[tuple[str, int], dict[str, str]]]) -> None:
...
注意,None
是一种类型提示特例,已被 type(None)
取代。
NewType
Use the NewType
helper class to create distinct types:
from typing import NewType
UserId = NewType('UserId', int)
some_id = UserId(524313)
静态类型检查器把新类型当作原始类型的子类,这种方式适用于捕捉逻辑错误:
def get_user_name(user_id: UserId) -> str:
...
# typechecks
user_a = get_user_name(UserId(42351))
# does not typecheck; an int is not a UserId
user_b = get_user_name(-1)
UserId
类型的变量可执行所有 int
操作,但返回结果都是 int
类型。这种方式允许在预期 int
时传入 UserId
,还能防止意外创建无效的 UserId
:
# 'output' is of type 'int', not 'UserId'
output = UserId(23413) + UserId(54341)
Note that these checks are enforced only by the static type checker. At runtime, the statement Derived = NewType('Derived', Base)
will make Derived
a class that immediately returns whatever parameter you pass it. That means the expression Derived(some_value)
does not create a new class or introduce much overhead beyond that of a regular function call.
更确切地说,在运行时,some_value is Derived(some_value)
表达式总为 True。
It is invalid to create a subtype of Derived
:
from typing import NewType
UserId = NewType('UserId', int)
# Fails at runtime and does not typecheck
class AdminUserId(UserId): pass
However, it is possible to create a NewType
based on a ‘derived’ NewType
:
from typing import NewType
UserId = NewType('UserId', int)
ProUserId = NewType('ProUserId', UserId)
同时,ProUserId
的类型检查也可以按预期执行。
详见 PEP 484。
注解
回顾上文,类型别名声明了两种彼此 等价 的类型。 Alias = Original
时,静态类型检查器认为 Alias
与 Original
完全等价。 这种方式适用于简化复杂类型签名。
反之,NewType
声明把一种类型当作另一种类型的 子类型*。Derived = NewType('Derived', Original)
时,静态类型检查器把 Derived
当作 Original
的 *子类 ,即,Original
类型的值不能用在预期 Derived
类型的位置。这种方式适用于以最小运行时成本防止逻辑错误。
3.5.2 新版功能.
在 3.10 版更改: NewType
is now a class rather than a function. There is some additional runtime cost when calling NewType
over a regular function. However, this cost will be reduced in 3.11.0.
可调对象(Callable)
预期特定签名回调函数的框架可以用 Callable[[Arg1Type, Arg2Type], ReturnType]
实现类型提示。
例如:
from collections.abc import Callable
def feeder(get_next_item: Callable[[], str]) -> None:
# Body
def async_query(on_success: Callable[[int], None],
on_error: Callable[[int, Exception], None]) -> None:
# Body
无需指定调用签名,用省略号字面量替换类型提示里的参数列表: Callable[..., ReturnType]
,就可以声明可调对象的返回类型。
Callables which take other callables as arguments may indicate that their parameter types are dependent on each other using ParamSpec
. Additionally, if that callable adds or removes arguments from other callables, the Concatenate
operator may be used. They take the form Callable[ParamSpecVariable, ReturnType]
and Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType]
respectively.
在 3.10 版更改: Callable
now supports ParamSpec
and Concatenate
. See PEP 612 for more information.
参见
The documentation for ParamSpec
and Concatenate
provide examples of usage in Callable
.
泛型(Generic)
容器中,对象的类型信息不能以泛型方式静态推断,因此,抽象基类扩展支持下标,用于表示容器元素的预期类型。
from collections.abc import Mapping, Sequence
def notify_by_email(employees: Sequence[Employee],
overrides: Mapping[str, str]) -> None: ...
typing 模块中新推出的 TypeVar
工厂函数实现泛型参数化。
from collections.abc import Sequence
from typing import TypeVar
T = TypeVar('T') # Declare type variable
def first(l: Sequence[T]) -> T: # Generic function
return l[0]
用户定义的泛型类型
用户定义的类可以定义为泛型类。
from typing import TypeVar, Generic
from logging import Logger
T = TypeVar('T')
class LoggedVar(Generic[T]):
def __init__(self, value: T, name: str, logger: Logger) -> None:
self.name = name
self.logger = logger
self.value = value
def set(self, new: T) -> None:
self.log('Set ' + repr(self.value))
self.value = new
def get(self) -> T:
self.log('Get ' + repr(self.value))
return self.value
def log(self, message: str) -> None:
self.logger.info('%s: %s', self.name, message)
Generic[T]
是定义类 LoggedVar
的基类,该类使用单类型参数 T
。在该类体内,T
是有效的类型。
Generic
基类定义了 __class_getitem__()
,因此,LoggedVar[t]
也是有效类型:
from collections.abc import Iterable
def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None:
for var in vars:
var.set(0)
泛型类型支持多个类型变量,不过,类型变量可能会受到限制:
from typing import TypeVar, Generic
...
T = TypeVar('T')
S = TypeVar('S', int, str)
class StrangePair(Generic[T, S]):
...
Generic
类型变量的参数应各不相同。下列代码就是无效的:
from typing import TypeVar, Generic
...
T = TypeVar('T')
class Pair(Generic[T, T]): # INVALID
...
Generic
支持多重继承:
from collections.abc import Sized
from typing import TypeVar, Generic
T = TypeVar('T')
class LinkedList(Sized, Generic[T]):
...
继承自泛型类时,可以修正某些类型变量:
from collections.abc import Mapping
from typing import TypeVar
T = TypeVar('T')
class MyDict(Mapping[str, T]):
...
比如,本例中 MyDict
调用的单参数,T
。
未指定泛型类的类型参数时,每个位置的类型都预设为 Any
。下例中,MyIterable
不是泛型,但却隐式继承了 Iterable[Any]
:
from collections.abc import Iterable
class MyIterable(Iterable): # Same as Iterable[Any]
还支持用户定义的泛型类型别名。例如:
from collections.abc import Iterable
from typing import TypeVar
S = TypeVar('S')
Response = Iterable[S] | int
# Return type here is same as Iterable[str] | int
def response(query: str) -> Response[str]:
...
T = TypeVar('T', int, float, complex)
Vec = Iterable[tuple[T, T]]
def inproduct(v: Vec[T]) -> T: # Same as Iterable[tuple[T, T]]
return sum(x*y for x, y in v)
在 3.7 版更改: Generic
不再支持自定义元类。
User-defined generics for parameter expressions are also supported via parameter specification variables in the form Generic[P]
. The behavior is consistent with type variables’ described above as parameter specification variables are treated by the typing module as a specialized type variable. The one exception to this is that a list of types can be used to substitute a ParamSpec
:
>>> from typing import Generic, ParamSpec, TypeVar
>>> T = TypeVar('T')
>>> P = ParamSpec('P')
>>> class Z(Generic[T, P]): ...
...
>>> Z[int, [dict, float]]
__main__.Z[int, (<class 'dict'>, <class 'float'>)]
Furthermore, a generic with only one parameter specification variable will accept parameter lists in the forms X[[Type1, Type2, ...]]
and also X[Type1, Type2, ...]
for aesthetic reasons. Internally, the latter is converted to the former and are thus equivalent:
>>> class X(Generic[P]): ...
...
>>> X[int, str]
__main__.X[(<class 'int'>, <class 'str'>)]
>>> X[[int, str]]
__main__.X[(<class 'int'>, <class 'str'>)]
Do note that generics with ParamSpec
may not have correct __parameters__
after substitution in some cases because they are intended primarily for static type checking.
在 3.10 版更改: Generic
can now be parameterized over parameter expressions. See ParamSpec
and PEP 612 for more details.
抽象基类可作为用户定义的泛型类的基类,且不会与元类冲突。现已不再支持泛型元类。参数化泛型的输出结果会被缓存,typing 模块的大多数类型都可哈希、可进行等价对比。
Any
类型
Any
是一种特殊的类型。静态类型检查器认为所有类型均与 Any
兼容,同样,Any
也与所有类型兼容。
也就是说,可对 Any
类型的值执行任何操作或方法调用,并赋值给任意变量:
from typing import Any
a = None # type: Any
a = [] # OK
a = 2 # OK
s = '' # type: str
s = a # OK
def foo(item: Any) -> int:
# Typechecks; 'item' could be any type,
# and that type might have a 'bar' method
item.bar()
...
注意,Any
类型的值赋给更精确的类型时,不执行类型检查。例如,把 a
赋给 s
,在运行时,即便 s
已声明为 str
类型,但接收 int
值时,静态类型检查器也不会报错。
此外,未指定返回值与参数类型的函数,都隐式地默认使用 Any
:
def legacy_parser(text):
...
return data
# A static type checker will treat the above
# as having the same signature as:
def legacy_parser(text: Any) -> Any:
...
return data
需要混用动态与静态类型代码时,此操作把 Any
当作 应急出口。
Any
和 object
的区别。与 Any
相似,所有类型都是 object
的子类型。然而,与 Any
不同,object 不可逆:object
不是 其它类型的子类型。
就是说,值的类型是 object
时,类型检查器几乎会拒绝所有对它的操作,并且,把它赋给更精确的类型变量(或返回值)属于类型错误。例如:
def hash_a(item: object) -> int:
# Fails; an object does not have a 'magic' method.
item.magic()
...
def hash_b(item: Any) -> int:
# Typechecks
item.magic()
...
# Typechecks, since ints and strs are subclasses of object
hash_a(42)
hash_a("foo")
# Typechecks, since Any is compatible with all types
hash_b(42)
hash_b("foo")
使用 object
,说明值能以类型安全的方式转为任何类型。使用 Any
,说明值是动态类型。
名义子类型 vs 结构子类型
PEP 484 最初只是把 Python 静态类型系统定义为应用 名义子类型。即,当且仅当 A
是 B
的子类时,才能在预期 B
类时应用 A
类。
此项要求以前也适用于抽象基类,例如,Iterable
。这种方式的问题在于,定义类时必须显式说明,既不 Pythonic,也不是动态类型式 Python 代码的惯用写法。例如,下列代码就遵从了 PEP 484 的规范:
from collections.abc import Sized, Iterable, Iterator
class Bucket(Sized, Iterable[int]):
...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[int]: ...
PEP 544 允许用户在类定义时不显式说明基类,从而解决了这一问题,静态类型检查器隐式认为 Bucket
既是 Sized
的子类型,又是 Iterable[int]
的子类型。这就是 结构子类型 (又称为静态鸭子类型):
from collections.abc import Iterator, Iterable
class Bucket: # Note: no base classes
...
def __len__(self) -> int: ...
def __iter__(self) -> Iterator[int]: ...
def collect(items: Iterable[int]) -> int: ...
result = collect(Bucket()) # Passes type check
此外,结构子类型的优势在于,通过继承特殊类 Protocol
,用户可以定义新的自定义协议(见下文中的例子)。
模块内容
本模块定义了下列类、函数和修饰器。
注解
本模块定义了一些类型,作为标准库中已有的类的子类,从而可以让 Generic
支持 []
中的类型变量。Python 3.9 中,这些标准库的类已支持 []
,因此,这些类型就变得冗余了。
Python 3.9 弃用了这些冗余类型,但解释器并未提供相应的弃用警告。标记弃用类型的工作留待支持 Python 3.9 及以上版本的类型检查器实现。
Python 3.9.0 发布五年后的首个 Python 发行版将从 typing
模块中移除这些弃用类型。详见 PEP 585 《标准集合的类型提示泛型》。
特殊类型原语
特殊类型
这些类型可用于类型注解,但不支持 []
。
typing.Any
不受限的特殊类型。
- 所有类型都与
Any
兼容。 Any
与所有类型都兼容。
typing.NoReturn
标记没有返回值的函数的特殊类型。例如:
from typing import NoReturn
def stop() -> NoReturn:
raise RuntimeError('no way')
3.5.4 新版功能.
3.6.2 新版功能.
typing.TypeAlias
Special annotation for explicitly declaring a type alias. For example:
from typing import TypeAlias
Factors: TypeAlias = list[int]
See PEP 613 for more details about explicit type aliases.
3.10 新版功能.
特殊形式
可用于类型注解,且支持 []
,每种形式都有其独特的句法。
typing.Tuple
元组类型; Tuple[X, Y]
是二项元组类型,第一个元素的类型是 X,第二个元素的类型是 Y。空元组的类型可写为 Tuple[()]
。
例:Tuple[T1, T2]
是二项元组,类型变量分别为 T1 和 T2。Tuple[int, float, str]
是由整数、浮点数、字符串组成的三项元组。
可用省略号字面量指定同质变长元组,例如,Tuple[int, ...]
。Tuple
与 Tuple[Any, ...]
等价,也与 tuple
等价。
3.9 版后已移除: builtins.tuple
现已支持 []
。详见 PEP 585 与 Generic Alias Type。
typing.Union
Union type; Union[X, Y]
is equivalent to X | Y
and means either X or Y.
To define a union, use e.g. Union[int, str]
or the shorthand int | str
. Details:
参数必须是某种类型,且至少有一个。
联合类型之联合类型会被展平,例如:
Union[Union[int, str], float] == Union[int, str, float]
单参数之联合类型就是该参数自身,例如:
Union[int] == int # The constructor actually returns int
冗余的参数会被跳过,例如:
Union[int, str, int] == Union[int, str] == int | str
比较联合类型,不涉及参数顺序,例如:
Union[int, str] == Union[str, int]
You cannot subclass or instantiate a
Union
.不支持
Union[X][Y]
这种写法。
在 3.7 版更改: 在运行时,不要移除联合类型中的显式子类。
在 3.10 版更改: Unions can now be written as X | Y
. See union type expressions.
typing.Optional
可选类型。
Optional[X]
is equivalent to X | None
(or Union[X, None]
).
注意,可选类型与含默认值的可选参数不同。含默认值的可选参数不需要在类型注解上添加 Optional
限定符,因为它仅是可选的。例如:
def foo(arg: int = 0) -> None:
...
另一方面,显式应用 None
值时,不管该参数是否可选, Optional
都适用。例如:
def foo(arg: Optional[int] = None) -> None:
...
在 3.10 版更改: Optional can now be written as X | None
. See union type expressions.
typing.Callable
可调类型; Callable[[int], str]
是把(int)转为 str 的函数。
下标句法必须与参数列表和返回类型这两个值一起使用。参数列表只能是类型列表或省略号;返回类型只能是单一类型。
没有说明可选参数或关键字参数的句法;这类函数类型很少用作回调类型。Callable[..., ReturnType]
(省略号字面量)可用于为接受任意数量参数,并返回 ReturnType
的可调对象提供类型提示。纯 Callable
等价于 Callable[..., Any]
,进而等价于 collections.abc.Callable
。
Callables which take other callables as arguments may indicate that their parameter types are dependent on each other using ParamSpec
. Additionally, if that callable adds or removes arguments from other callables, the Concatenate
operator may be used. They take the form Callable[ParamSpecVariable, ReturnType]
and Callable[Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable], ReturnType]
respectively.
3.9 版后已移除: collections.abc.Callable
现已支持 []
。 详见 PEP 585 与 Generic Alias Type。
在 3.10 版更改: Callable
now supports ParamSpec
and Concatenate
. See PEP 612 for more information.
参见
The documentation for ParamSpec
and Concatenate
provide examples of usage with Callable
.
typing.Concatenate
Used with Callable
and ParamSpec
to type annotate a higher order callable which adds, removes, or transforms parameters of another callable. Usage is in the form Concatenate[Arg1Type, Arg2Type, ..., ParamSpecVariable]
. Concatenate
is currently only valid when used as the first argument to a Callable
. The last parameter to Concatenate
must be a ParamSpec
.
For example, to annotate a decorator with_lock
which provides a threading.Lock
to the decorated function, Concatenate
can be used to indicate that with_lock
expects a callable which takes in a Lock
as the first argument, and returns a callable with a different type signature. In this case, the ParamSpec
indicates that the returned callable’s parameter types are dependent on the parameter types of the callable being passed in:
from collections.abc import Callable
from threading import Lock
from typing import Any, Concatenate, ParamSpec, TypeVar
P = ParamSpec('P')
R = TypeVar('R')
# Use this lock to ensure that only one thread is executing a function
# at any time.
my_lock = Lock()
def with_lock(f: Callable[Concatenate[Lock, P], R]) -> Callable[P, R]:
'''A type-safe decorator which provides a lock.'''
global my_lock
def inner(*args: P.args, **kwargs: P.kwargs) -> R:
# Provide the lock as the first argument.
return f(my_lock, *args, **kwargs)
return inner
@with_lock
def sum_threadsafe(lock: Lock, numbers: list[float]) -> float:
'''Add a list of numbers together in a thread-safe manner.'''
with lock:
return sum(numbers)
# We don't need to pass in the lock ourselves thanks to the decorator.
sum_threadsafe([1.1, 2.2, 3.3])
3.10 新版功能.
参见
- PEP 612 — Parameter Specification Variables (the PEP which introduced
ParamSpec
andConcatenate
). ParamSpec
andCallable
.
class typing.Type
(Generic[CT_co])
用 C
注解的变量可以接受类型 C
的值。反之,用 Type[C]
注解的变量可以接受类自身的值 — 准确地说,是接受 C
的 类对象,例如:
a = 3 # Has type 'int'
b = int # Has type 'Type[int]'
c = type(a) # Also has type 'Type[int]'
注意,Type[C]
为协变量:
class User: ...
class BasicUser(User): ...
class ProUser(User): ...
class TeamUser(User): ...
# Accepts User, BasicUser, ProUser, TeamUser, ...
def make_new_user(user_class: Type[User]) -> User:
# ...
return user_class()
Type[C]
为协变量的意思是指, C
的所有子类都应使用与 C
相同的构造器签名及类方法签名。类型检查器应标记违反此项规定的内容,但也应允许符合指定基类构造器调用的子类进行构造器调用。PEP 484 修订版将来可能会调整类型检查器对这种特例的处理方式。
Type
合法的参数仅有类、Any
、类型变量 以及上述类型的联合类型。例如:
def new_non_team_user(user_class: Type[BasicUser | ProUser]):
...
Type[Any]
等价于 Type
,进而等价于 Python 元类架构的根基,type
。
3.5.2 新版功能.
3.9 版后已移除: builtins.type
现已支持 []
。详见 PEP 585 与 Generic Alias Type。
typing.Literal
表示类型检查器对应变量或函数参数的值等价于给定字面量(或多个字面量之一)的类型。例如:
def validate_simple(data: Any) -> Literal[True]: # always returns True
...
MODE = Literal['r', 'rb', 'w', 'wb']
def open_helper(file: str, mode: MODE) -> str:
...
open_helper('/some/path', 'r') # Passes type check
open_helper('/other/path', 'typo') # Error in type checker
Literal[...]
不能创建子类。在运行时,任意值均可作为 Literal[...]
的类型参数,但类型检查器可以对此加以限制。字面量类型详见 PEP 586 。
3.8 新版功能.
在 3.9.1 版更改: Literal
现在能去除形参的重复。 Literal
对象的相等性比较不再依赖顺序。 现在如果有某个参数不为 hashable,Literal
对象在相等性比较期间将引发 TypeError
。
typing.ClassVar
标记类变量的特殊类型构造器。
如 PEP 526 所述,打包在 ClassVar 内的变量注解是指,给定属性应当用作类变量,而不应设置在类实例上。用法如下:
class Starship:
stats: ClassVar[dict[str, int]] = {} # class variable
damage: int = 10 # instance variable
ClassVar
仅接受类型,也不能使用下标。
ClassVar
本身不是类,不应用于 isinstance()
或 issubclass()
。ClassVar
不改变 Python 运行时行为,但可以用于第三方类型检查器。例如,类型检查器会认为以下代码有错:
enterprise_d = Starship(3000)
enterprise_d.stats = {} # Error, setting class variable on instance
Starship.stats = {} # This is OK
3.5.3 新版功能.
typing.Final
告知类型检查器某名称不能再次赋值或在子类中重写的特殊类型构造器。例如:
MAX_SIZE: Final = 9000
MAX_SIZE += 1 # Error reported by type checker
class Connection:
TIMEOUT: Final[int] = 10
class FastConnector(Connection):
TIMEOUT = 1 # Error reported by type checker
这些属性没有运行时检查。详见 PEP 591。
3.8 新版功能.
typing.Annotated
PEP 593 (灵活函数和变量注解
)里引入的类型,可以用上下文特定元数据(Annotated
的参数可变,也可能用它的多个组成部分)装饰现有的类型。具体来说,就是类型提示 Annotated[T, x]
用元数据 x
注解类型 T
。静态分析或运行时都能使用该元数据。库(或工具)处理类型提示 Annotated[T, x]
时,在元数据 x
不涉及特殊逻辑的情况下,可忽略该类型提示,仅把它当作类型 T
。与 typing
模块中现有的 no_type_check
功能不同,该功能完全禁用了函数或类的类型检查注解,而 Annotated
类型则允许对 T
进行静态类型检查(例如,通过 mypy 或 Pyre,可安全地忽略 x
),也可以在特定应用程序中实现 x
的运行时访问。
毕竟,如何解释注解(如有)由处理 Annotated
类型的工具/库负责。工具/库处理 Annotated
类型时,扫描所有注解以确定是否需要进行处理(例如,使用 isinstance()
)。
工具/库不支持注解,或遇到未知注解时,应忽略注解,并把注解类型当作底层类型。
是否允许客户端在一个类型上使用多个注解,以及如何合并这些注解,由处理注解的工具决定。
Annotated
类型支持把多个相同(或不同)的单个(或多个)类型注解置于任意节点。因此,使用这些注解的工具/库要负责处理潜在的重复项。例如,执行值范围分析时,应允许以下操作:
T1 = Annotated[int, ValueRange(-10, 5)]
T2 = Annotated[T1, ValueRange(-20, 3)]
传递 include_extras=True
至 get_type_hints()
,即可在运行时访问额外的注解。
语义详情:
Annotated
的第一个参数必须是有效类型。支持多个类型标注(
Annotated
支持可变参数):Annotated[int, ValueRange(3, 10), ctype("char")]
调用
Annotated
至少要有两个参数(Annotated[int]
是无效的)注解的顺序会被保留,且影响等价检查:
Annotated[int, ValueRange(3, 10), ctype("char")] != Annotated[ int, ctype("char"), ValueRange(3, 10) ]
嵌套
Annotated
类型会被展平,元数据从最内层注解依序展开:Annotated[Annotated[int, ValueRange(3, 10)], ctype("char")] == Annotated[ int, ValueRange(3, 10), ctype("char") ]
不移除注解重复项:
Annotated[int, ValueRange(3, 10)] != Annotated[ int, ValueRange(3, 10), ValueRange(3, 10) ]
Annotated
可用于嵌套或泛型别名:T = TypeVar('T') Vec = Annotated[list[tuple[T, T]], MaxLen(10)] V = Vec[int] V == Annotated[list[tuple[int, int]], MaxLen(10)]
3.9 新版功能.
typing.TypeGuard
Special typing form used to annotate the return type of a user-defined type guard function. TypeGuard
only accepts a single type argument. At runtime, functions marked this way should return a boolean.
TypeGuard
aims to benefit type narrowing — a technique used by static type checkers to determine a more precise type of an expression within a program’s code flow. Usually type narrowing is done by analyzing conditional code flow and applying the narrowing to a block of code. The conditional expression here is sometimes referred to as a “type guard”:
def is_str(val: str | float):
# "isinstance" type guard
if isinstance(val, str):
# Type of ``val`` is narrowed to ``str``
...
else:
# Else, type of ``val`` is narrowed to ``float``.
...
Sometimes it would be convenient to use a user-defined boolean function as a type guard. Such a function should use TypeGuard[...]
as its return type to alert static type checkers to this intention.
Using -> TypeGuard
tells the static type checker that for a given function:
The return value is a boolean.
If the return value is
True
, the type of its argument is the type insideTypeGuard
.例如:
def is_str_list(val: List[object]) -> TypeGuard[List[str]]: '''Determines whether all objects in the list are strings''' return all(isinstance(x, str) for x in val) def func1(val: List[object]): if is_str_list(val): # Type of ``val`` is narrowed to ``List[str]``. print(" ".join(val)) else: # Type of ``val`` remains as ``List[object]``. print("Not a list of strings!")
If is_str_list
is a class or instance method, then the type in TypeGuard
maps to the type of the second parameter after cls
or self
.
In short, the form def foo(arg: TypeA) -> TypeGuard[TypeB]: ...
, means that if foo(arg)
returns True
, then arg
narrows from TypeA
to TypeB
.
注解
TypeB
need not be a narrower form of TypeA
— it can even be a wider form. The main reason is to allow for things like narrowing List[object]
to List[str]
even though the latter is not a subtype of the former, since List
is invariant. The responsibility of writing type-safe type guards is left to the user.
TypeGuard
also works with type variables. For more information, see PEP 647 (User-Defined Type Guards).
3.10 新版功能.
构建泛型类型
以下内容是创建泛型类型的基石,但不在注解内使用。
class typing.Generic
用于泛型类型的抽象基类。
泛型类型一般通过继承含一个或多个类型变量的类实例进行声明。例如,泛型映射类型定义如下:
class Mapping(Generic[KT, VT]):
def __getitem__(self, key: KT) -> VT:
...
# Etc.
该类的用法如下:
X = TypeVar('X')
Y = TypeVar('Y')
def lookup_name(mapping: Mapping[X, Y], key: X, default: Y) -> Y:
try:
return mapping[key]
except KeyError:
return default
class typing.TypeVar
类型变量。
用法:
T = TypeVar('T') # Can be anything
A = TypeVar('A', str, bytes) # Must be str or bytes
类型变量主要是为静态类型检查器提供支持,用于泛型类型与泛型函数定义的参数。有关泛型类型。泛型函数的写法如下:
def repeat(x: T, n: int) -> Sequence[T]:
"""Return a list containing n references to x."""
return [x]*n
def longest(x: A, y: A) -> A:
"""Return the longest of two strings."""
return x if len(x) >= len(y) else y
本质上,后例的签名重载了 (str, str) -> str
与 (bytes, bytes) -> bytes
。注意,参数是 str
子类的实例时,返回类型仍是纯 str
。
在运行时,isinstance(x, T)
会触发 TypeError
异常。一般而言,isinstance()
和 issubclass()
不应与类型搭配使用。
通过 covariant=True
或 contravariant=True
可以把类型变量标记为协变量或逆变量。详见 PEP 484。默认情况下,类型变量是不变量。类型变量还可以用 bound=<type>
指定上限。这里的意思是,(显式或隐式地)取代类型变量的实际类型必须是限定类型的子类,详见 PEP 484。
class typing.ParamSpec
(name, **, bound=None, covariant=False, contravariant=False*)
Parameter specification variable. A specialized version of type variables
.
用法:
P = ParamSpec('P')
Parameter specification variables exist primarily for the benefit of static type checkers. They are used to forward the parameter types of one callable to another callable — a pattern commonly found in higher order functions and decorators. They are only valid when used in Concatenate
, or as the first argument to Callable
, or as parameters for user-defined Generics. See Generic
for more information on generic types.
For example, to add basic logging to a function, one can create a decorator add_logging
to log function calls. The parameter specification variable tells the type checker that the callable passed into the decorator and the new callable returned by it have inter-dependent type parameters:
from collections.abc import Callable
from typing import TypeVar, ParamSpec
import logging
T = TypeVar('T')
P = ParamSpec('P')
def add_logging(f: Callable[P, T]) -> Callable[P, T]:
'''A type-safe decorator to add logging to a function.'''
def inner(*args: P.args, **kwargs: P.kwargs) -> T:
logging.info(f'{f.__name__} was called')
return f(*args, **kwargs)
return inner
@add_logging
def add_two(x: float, y: float) -> float:
'''Add two numbers together.'''
return x + y
Without ParamSpec
, the simplest way to annotate this previously was to use a TypeVar
with bound Callable[..., Any]
. However this causes two problems:
- The type checker can’t type check the
inner
function because*args
and**kwargs
have to be typedAny
.cast()
may be required in the body of theadd_logging
decorator when returning theinner
function, or the static type checker must be told to ignore thereturn inner
.
args
kwargs
Since
ParamSpec
captures both positional and keyword parameters,P.args
andP.kwargs
can be used to split aParamSpec
into its components.P.args
represents the tuple of positional parameters in a given call and should only be used to annotate*args
.P.kwargs
represents the mapping of keyword parameters to their values in a given call, and should be only be used to annotate**kwargs
. Both attributes require the annotated parameter to be in scope. At runtime,P.args
andP.kwargs
are instances respectively ofParamSpecArgs
andParamSpecKwargs
.
Parameter specification variables created with covariant=True
or contravariant=True
can be used to declare covariant or contravariant generic types. The bound
argument is also accepted, similar to TypeVar
. However the actual semantics of these keywords are yet to be decided.
3.10 新版功能.
注解
Only parameter specification variables defined in global scope can be pickled.
参见
- PEP 612 — Parameter Specification Variables (the PEP which introduced
ParamSpec
andConcatenate
). Callable
andConcatenate
.
typing.ParamSpecArgs
typing.ParamSpecKwargs
Arguments and keyword arguments attributes of a ParamSpec
. The P.args
attribute of a ParamSpec
is an instance of ParamSpecArgs
, and P.kwargs
is an instance of ParamSpecKwargs
. They are intended for runtime introspection and have no special meaning to static type checkers.
Calling get_origin()
on either of these objects will return the original ParamSpec
:
P = ParamSpec("P")
get_origin(P.args) # returns P
get_origin(P.kwargs) # returns P
3.10 新版功能.
typing.AnyStr
AnyStr
类型变量的定义为 AnyStr = TypeVar('AnyStr', str, bytes)
。
这里指的是,它可以接受任意同类字符串,但不支持混用不同类别的字符串。例如:
def concat(a: AnyStr, b: AnyStr) -> AnyStr:
return a + b
concat(u"foo", u"bar") # Ok, output has type 'unicode'
concat(b"foo", b"bar") # Ok, output has type 'bytes'
concat(u"foo", b"bar") # Error, cannot mix unicode and bytes
class typing.Protocol
(Generic)
Protocol 类的基类。Protocol 类的定义如下:
class Proto(Protocol):
def meth(self) -> int:
...
这些类主要与静态类型检查器搭配使用,用来识别结构子类型(静态鸭子类型),例如:
class C:
def meth(self) -> int:
return 0
def func(x: Proto) -> int:
return x.meth()
func(C()) # Passes static type check
详见 PEP 544。Protocol 类用 runtime_checkable()
(见下文)装饰,忽略类型签名,仅检查给定属性是否存在,充当简要的运行时协议。
Protocol 类可以是泛型,例如:
class GenProto(Protocol[T]):
def meth(self) -> T:
...
3.8 新版功能.
@``typing.runtime_checkable
用于把 Protocol 类标记为运行时协议。
该协议可以与 isinstance()
和 issubclass()
一起使用。应用于非协议的类时,会触发 TypeError
。该指令支持简易结构检查,与 collections.abc
的 Iterable
非常类似,只擅长做一件事。 例如:
@runtime_checkable
class Closable(Protocol):
def close(self): ...
assert isinstance(open('/some/file'), Closable)
注解
runtime_checkable()
will check only the presence of the required methods, not their type signatures. For example, ssl.SSLObject
is a class, therefore it passes an issubclass()
check against Callable
. However, the ssl.SSLObject.__init__()
method exists only to raise a TypeError
with a more informative message, therefore making it impossible to call (instantiate) ssl.SSLObject
.
3.8 新版功能.
其他特殊指令
这些特殊指令是声明类型的基石,但不在注解内使用。
class typing.NamedTuple
collections.namedtuple()
的类型版本。
用法:
class Employee(NamedTuple):
name: str
id: int
这相当于:
Employee = collections.namedtuple('Employee', ['name', 'id'])
为字段提供默认值,要在类体内赋值:
class Employee(NamedTuple):
name: str
id: int = 3
employee = Employee('Guido')
assert employee.id == 3
带默认值的字段必须在不带默认值的字段后面。
生成的类具有 __annotations__
这个附加属性,提供了映射字段名与字段类型的字典。(字段名在 _fields
属性内,默认值在 _field_defaults
属性内,这两项都是命名元组 API 的组成部分。)
NamedTuple
子类也支持文档字符串与方法:
class Employee(NamedTuple):
"""Represents an employee."""
name: str
id: int = 3
def __repr__(self) -> str:
return f'<Employee {self.name}, id={self.id}>'
反向兼容用法:
Employee = NamedTuple('Employee', [('name', str), ('id', int)])
在 3.6 版更改: 添加了对 PEP 526 中变量注解句法的支持。
在 3.6.1 版更改: 添加了对默认值、方法、文档字符串的支持。
在 3.8 版更改: _field_types
和 __annotations__
属性现已使用常规字典,不再使用 OrderedDict
实例。
在 3.9 版更改: 移除了 _field_types
属性, 改用具有相同信息,但更标准的 __annotations__
属性。
class typing.NewType
(name, tp)
A helper class to indicate a distinct type to a typechecker, see NewType. At runtime it returns an object that returns its argument when called. Usage:
UserId = NewType('UserId', int)
first_user = UserId(1)
3.5.2 新版功能.
在 3.10 版更改: NewType
is now a class rather than a function.
class typing.TypedDict
(dict)
把类型提示添加至字典的特殊构造器。在运行时,它是纯 dict
。
TypedDict
声明一个字典类型,该类型预期所有实例都具有一组键集,其中,每个键都与对应类型的值关联。运行时不检查此预期,而是由类型检查器强制执行。用法如下:
class Point2D(TypedDict):
x: int
y: int
label: str
a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK
b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check
assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first')
The type info for introspection can be accessed via Point2D.__annotations__
, Point2D.__total__
, Point2D.__required_keys__
, and Point2D.__optional_keys__
. To allow using this feature with older versions of Python that do not support PEP 526, TypedDict
supports two additional equivalent syntactic forms:
Point2D = TypedDict('Point2D', x=int, y=int, label=str)
Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str})
By default, all keys must be present in a TypedDict
. It is possible to override this by specifying totality. Usage:
class Point2D(TypedDict, total=False):
x: int
y: int
This means that a Point2D
TypedDict
can have any of the keys omitted. A type checker is only expected to support a literal False
or True
as the value of the total
argument. True
is the default, and makes all items defined in the class body required.
更多示例与 TypedDict
的详细规则,详见 PEP 589。
3.8 新版功能.
泛型具象容器
对应的内置类型
class typing.Dict
(dict, MutableMapping[KT, VT])
dict
的泛型版本。适用于注解返回类型。注解参数时,最好使用 Mapping
等抽象容器类型。
该类型用法如下:
def count_words(text: str) -> Dict[str, int]:
...
3.9 版后已移除: builtins.dict
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.List
(list, MutableSequence[T])
list
的泛型版本。适用于注解返回类型。注解参数时,最好使用 Sequence
或 Iterable
等抽象容器类型。
该类型用法如下:
T = TypeVar('T', int, float)
def vec2(x: T, y: T) -> List[T]:
return [x, y]
def keep_positives(vector: Sequence[T]) -> List[T]:
return [item for item in vector if item > 0]
3.9 版后已移除: builtins.list
现已支持 []
。详见 PEP 585 与 Generic Alias Type。
class typing.Set
(set, MutableSet[T])
builtins.set
的泛型版本。适用于注解返回类型。注解参数时,最好使用 AbstractSet
等抽象容器类型。
3.9 版后已移除: builtins.set
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.FrozenSet
(frozenset, AbstractSet[T_co])
builtins.frozenset
的泛型版本。
3.9 版后已移除: builtins.frozenset
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
注解
Tuple
是一种特殊形式。
collections
对应类型
class typing.DefaultDict
(collections.defaultdict, MutableMapping[KT, VT])
collections.defaultdict
的泛型版本。
3.5.2 新版功能.
3.9 版后已移除: collections.defaultdict
现已支持 []
。详见 PEP 585 与 Generic Alias Type。
class typing.OrderedDict
(collections.OrderedDict, MutableMapping[KT, VT])
collections.OrderedDict
的泛型版本。
3.7.2 新版功能.
3.9 版后已移除: collections.OrderedDict
现已支持 []
。详见 PEP 585 与 Generic Alias Type。
class typing.ChainMap
(collections.ChainMap, MutableMapping[KT, VT])
collections.ChainMap
的泛型版本。
3.5.4 新版功能.
3.6.1 新版功能.
3.9 版后已移除: collections.ChainMap
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.Counter
(collections.Counter, Dict[T, int])
collections.Counter
的泛型版本。
3.5.4 新版功能.
3.6.1 新版功能.
3.9 版后已移除: collections.Counter
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.Deque
(deque, MutableSequence[T])
collections.deque
的泛型版本。
3.5.4 新版功能.
3.6.1 新版功能.
3.9 版后已移除: collections.deque
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
其他具象类型
class typing.IO
class typing.TextIO
class typing.BinaryIO
泛型类型 IO[AnyStr]
及其子类 TextIO(IO[str])
与 BinaryIO(IO[bytes])
表示 I/O 流的类型,例如 open()
所返回的对象。
Deprecated since version 3.8, will be removed in version 3.12: The typing.io
namespace is deprecated and will be removed. These types should be directly imported from typing
instead.
class typing.Pattern
class typing.Match
这些类型对应的是从 re.compile()
和 re.match()
返回的类型。 这些类型(及相应的函数)是 AnyStr
中的泛型并可通过编写 Pattern[str]
, Pattern[bytes]
, Match[str]
或 Match[bytes]
来具体指定。
Deprecated since version 3.8, will be removed in version 3.12: The typing.re
namespace is deprecated and will be removed. These types should be directly imported from typing
instead.
3.9 版后已移除: re
模块中的 Pattern
与 Match
类现已支持 []
。详见 PEP 585 与 Generic Alias Type。
class typing.Text
Text
是 str
的别名。提供了对 Python 2 代码的向下兼容:Python 2 中,Text
是 unicode
的别名。
使用 Text
时,值中必须包含 unicode 字符串,以兼容 Python 2 和 Python 3:
def add_unicode_checkmark(text: Text) -> Text:
return text + u' \u2713'
3.5.2 新版功能.
抽象基类
collections.abc
对应的容器
class typing.AbstractSet
(Sized, Collection[T_co])
collections.abc.Set
的泛型版本。
3.9 版后已移除: collections.abc.Set
现已支持 []
。详见 PEP 585 与 Generic Alias Type。
class typing.ByteString
(Sequence[int])
collections.abc.ByteString
的泛型版本。
该类型代表了 bytes
、bytearray
、memoryview
等字节序列类型。
作为该类型的简称,bytes
可用于标注上述任意类型的参数。
3.9 版后已移除: collections.abc.ByteString
现已支持 []
。详见 PEP 585 与 Generic Alias Type。
class typing.Collection
(Sized, Iterable[T_co], Container[T_co])
collections.abc.Collection
的泛型版本。
3.6.0 新版功能.
3.9 版后已移除: collections.abc.Collection
现已支持 []
。详见 PEP 585 与 Generic Alias Type。
class typing.Container
(Generic[T_co])
collections.abc.Container
的泛型版本。
3.9 版后已移除: collections.abc.Container
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.ItemsView
(MappingView, Generic[KT_co, VT_co])
collections.abc.ItemsView
的泛型版本。
3.9 版后已移除: collections.abc.ItemsView
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.KeysView
(MappingView[KT_co], AbstractSet[KT_co])
collections.abc.KeysView
的泛型版本。
3.9 版后已移除: collections.abc.KeysView
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.Mapping
(Sized, Collection[KT], Generic[VT_co])
collections.abc.Mapping
的泛型版本。用法如下:
def get_position_in_index(word_list: Mapping[str, int], word: str) -> int:
return word_list[word]
3.9 版后已移除: collections.abc.Mapping
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.MappingView
(Sized, Iterable[T_co])
collections.abc.MappingView
的泛型版本。
3.9 版后已移除: collections.abc.MappingView
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.MutableMapping
(Mapping[KT, VT])
collections.abc.MutableMapping
的泛型版本。
3.9 版后已移除: collections.abc.MutableMapping
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.MutableSequence
(Sequence[T])
collections.abc.MutableSequence
的泛型版本。
3.9 版后已移除: collections.abc.MutableSequence
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.MutableSet
(AbstractSet[T])
collections.abc.MutableSet
的泛型版本。
3.9 版后已移除: collections.abc.MutableSet
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.Sequence
(Reversible[T_co], Collection[T_co])
collections.abc.Sequence
的泛型版本。
3.9 版后已移除: collections.abc.Sequence
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.ValuesView
(MappingView[VT_co])
collections.abc.ValuesView
的泛型版本。
3.9 版后已移除: collections.abc.ValuesView
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
collections.abc
对应的其他类型
class typing.Iterable
(Generic[T_co])
collections.abc.Iterable
的泛型版本。
3.9 版后已移除: collections.abc.Iterable
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.Iterator
(Iterable[T_co])
collections.abc.Iterator
的泛型版本。
3.9 版后已移除: collections.abc.Iterator
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.Generator
(Iterator[T_co], Generic[T_co, T_contra, V_co])
生成器可以由泛型类型 Generator[YieldType, SendType, ReturnType]
注解。例如:
def echo_round() -> Generator[int, float, str]:
sent = yield 0
while sent >= 0:
sent = yield round(sent)
return 'Done'
注意,与 typing 模块里的其他泛型不同, Generator
的 SendType
属于逆变行为,不是协变行为,也是不变行为。
如果生成器只产生值,可将 SendType
与 ReturnType
设为 None
:
def infinite_stream(start: int) -> Generator[int, None, None]:
while True:
yield start
start += 1
此外,还可以把生成器的返回类型注解为 Iterable[YieldType]
或 Iterator[YieldType]
:
def infinite_stream(start: int) -> Iterator[int]:
while True:
yield start
start += 1
3.9 版后已移除: collections.abc.Generator
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.Hashable
collections.abc.Hashable
的别名。
class typing.Reversible
(Iterable[T_co])
collections.abc.Reversible
的泛型版本。
3.9 版后已移除: collections.abc.Reversible
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.Sized
collections.abc.Sized
的别名。
异步编程
class typing.Coroutine
(Awaitable[V_co], Generic[T_co, T_contra, V_co])
collections.abc.Coroutine
的泛型版本。类型变量的差异和顺序与 Generator
的内容相对应,例如:
from collections.abc import Coroutine
c = None # type: Coroutine[list[str], str, int]
...
x = c.send('hi') # type: list[str]
async def bar() -> None:
x = await c # type: int
3.5.3 新版功能.
3.9 版后已移除: collections.abc.Coroutine
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.AsyncGenerator
(AsyncIterator[T_co], Generic[T_co, T_contra])
异步生成器可由泛型类型 AsyncGenerator[YieldType, SendType]
注解。例如:
async def echo_round() -> AsyncGenerator[int, float]:
sent = yield 0
while sent >= 0.0:
rounded = await round(sent)
sent = yield rounded
与常规生成器不同,异步生成器不能返回值,因此没有 ReturnType
类型参数。 与 Generator
类似,SendType
也属于逆变行为。
如果生成器只产生值,可将 SendType
设置为 None
:
async def infinite_stream(start: int) -> AsyncGenerator[int, None]:
while True:
yield start
start = await increment(start)
此外,可用 AsyncIterable[YieldType]
或 AsyncIterator[YieldType]
注解生成器的返回类型:
async def infinite_stream(start: int) -> AsyncIterator[int]:
while True:
yield start
start = await increment(start)
3.6.1 新版功能.
3.9 版后已移除: collections.abc.AsyncGenerator
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.AsyncIterable
(Generic[T_co])
collections.abc.AsyncIterable
的泛型版本。
3.5.2 新版功能.
3.9 版后已移除: collections.abc.AsyncIterable
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.AsyncIterator
(AsyncIterable[T_co])
collections.abc.AsyncIterator
的泛型版本。
3.5.2 新版功能.
3.9 版后已移除: collections.abc.AsyncIterator
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.Awaitable
(Generic[T_co])
collections.abc.Awaitable
的泛型版本。
3.5.2 新版功能.
3.9 版后已移除: collections.abc.Awaitable
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
上下文管理器类型
class typing.ContextManager
(Generic[T_co])
contextlib.AbstractContextManager
的泛型版本。
3.5.4 新版功能.
3.6.0 新版功能.
3.9 版后已移除: contextlib.AbstractContextManager
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
class typing.AsyncContextManager
(Generic[T_co])
contextlib.AbstractAsyncContextManager
的泛型版本。
3.5.4 新版功能.
3.6.2 新版功能.
3.9 版后已移除: contextlib.AbstractAsyncContextManager
现已支持 []
。详见 PEP 585 和 Generic Alias Type。
协议
这些协议由 runtime_checkable()
装饰。
class typing.SupportsAbs
含抽象方法 __abs__
的抽象基类,是其返回类型里的协变量。
class typing.SupportsBytes
含抽象方法 __bytes__
的抽象基类。
class typing.SupportsComplex
含抽象方法 __complex__
的抽象基类。
class typing.SupportsFloat
含抽象方法 __float__
的抽象基类。
class typing.SupportsIndex
含抽象方法 __index__
的抽象基类。
3.8 新版功能.
class typing.SupportsInt
含抽象方法 __int__
的抽象基类。
class typing.SupportsRound
含抽象方法 __round__
的抽象基类,是其返回类型的协变量。
函数与装饰器
typing.cast
(typ, val)
把值强制转换为类型。
不变更返回值。对类型检查器而言,代表了返回值具有指定的类型,但运行时故意不做任何检查(以便让检查速度尽量快)。
@``typing.overload
@overload
装饰器可以修饰支持多个不同参数类型组合的函数或方法。@overload
- 装饰定义的系列必须紧跟一个非 @overload
-装饰定义(用于同一个函数/方法)。@overload
-装饰定义仅是为了协助类型检查器, 因为该装饰器会被非 @overload
-装饰定义覆盖,后者用于运行时,而且会被类型检查器忽略。在运行时直接调用 @overload
装饰的函数会触发 NotImplementedError
。下面的重载示例给出了比联合类型或类型变量更精准的类型:
@overload
def process(response: None) -> None:
...
@overload
def process(response: int) -> tuple[int, str]:
...
@overload
def process(response: bytes) -> str:
...
def process(response):
<actual implementation>
详见 PEP 484,与其他类型语义进行对比。
@``typing.final
告知类型检查器被装饰的方法不能被覆盖,且被装饰的类不能作为子类的装饰器,例如:
class Base:
@final
def done(self) -> None:
...
class Sub(Base):
def done(self) -> None: # Error reported by type checker
...
@final
class Leaf:
...
class Other(Leaf): # Error reported by type checker
...
这些属性没有运行时检查。详见 PEP 591。
3.8 新版功能.
@``typing.no_type_check
标明注解不是类型提示的装饰器。
用作类或函数的 decorator。用于类时,递归地应用于该类中定义的所有方法,(但不影响超类或子类中定义的方法)。
本方法可直接修改函数。
@``typing.no_type_check_decorator
让其他装饰器具有 no_type_check()
效果的装饰器。
本装饰器用 no_type_check()
里的装饰函数打包其他装饰器。
@``typing.type_check_only
标记类或函数内不可用于运行时的装饰器。
在运行时,该装饰器本身不可用。实现返回的是私有类实例时,它主要是用于标记在类型存根文件中定义的类。
@type_check_only
class Response: # private or not available at runtime
code: int
def get_header(self, name: str) -> str: ...
def fetch_response() -> Response: ...
注意,建议不要返回私有类实例,最好将之设为公共类。
内省辅助器
typing.get_type_hints
(obj, globalns=None, localns=None, include_extras=False)
返回函数、方法、模块、类对象的类型提示的字典。
一般情况下,与 obj.__annotations__
相同。此外,可通过在 globals
与 locals
命名空间里进行评估,以此来处理编码为字符串字面量的前向引用。如有需要,在默认值设置为 None
时,可为函数或方法注解添加 Optional[t]
。对于类 C
,则返回由所有 __annotations__
与 C.__mro__
逆序合并而成的字典。
本函数以递归地方式用 T
替换所有 Annotated[T, ...]
, 除非将 include_extras
的值设置为 True
。例如:
class Student(NamedTuple):
name: Annotated[str, 'some marker']
get_type_hints(Student) == {'name': str}
get_type_hints(Student, include_extras=False) == {'name': str}
get_type_hints(Student, include_extras=True) == {
'name': Annotated[str, 'some marker']
}
注解
get_type_hints()
does not work with imported type aliases that include forward references. Enabling postponed evaluation of annotations (PEP 563) may remove the need for most forward references.
在 3.9 版更改: PEP 593 的组成部分,添加了 include_extras
参数。
typing.get_args
(tp)
typing.get_origin
(tp)
为泛型类型与特殊类型形式提供了基本的内省功能。
For a typing object of the form X[Y, Z, ...]
these functions return X
and (Y, Z, ...)
. If X
is a generic alias for a builtin or collections
class, it gets normalized to the original class. If X
is a union or Literal
contained in another generic type, the order of (Y, Z, ...)
may be different from the order of the original arguments [Y, Z, ...]
due to type caching. For unsupported objects return None
and ()
correspondingly. Examples:
assert get_origin(Dict[str, int]) is dict
assert get_args(Dict[int, str]) == (int, str)
assert get_origin(Union[int, str]) is Union
assert get_args(Union[int, str]) == (int, str)
3.8 新版功能.
typing.is_typeddict
(tp)
Check if a type is a TypedDict
.
例如:
class Film(TypedDict):
title: str
year: int
is_typeddict(Film) # => True
is_typeddict(list | str) # => False
3.10 新版功能.
class typing.ForwardRef
用于字符串前向引用的内部类型表示的类。 例如,List["SomeClass"]
会被隐式转换为 List[ForwardRef("SomeClass")]
。 这个类不应由用户来实例化,但可以由内省工具使用。
注解
PEP 585 泛型类型例如 list["SomeClass"]
将不会被隐式地转换为 list[ForwardRef("SomeClass")]
因而将不会自动解析为 list[SomeClass]
。
3.7.4 新版功能.
常量
typing.TYPE_CHECKING
被第三方静态类型检查器假定为 True
的特殊常量。 在运行时为 False
。 用法如下:
if TYPE_CHECKING:
import expensive_mod
def fun(arg: 'expensive_mod.SomeType') -> None:
local_var: expensive_mod.AnotherType = other_fun()
第一个类型注解必须用引号标注,才能把它当作“前向引用”,从而在解释器运行时中隐藏 expensive_mod
引用。局部变量的类型注释不会被评估,因此,第二个注解不需要用引号引起来。
注解
Python 3.7 或更高版本中使用 from __future__ import
时,函数定义时不处理注解, 而是把注解当作字符串存在 __annotations__
里,这样就不必为注解使用引号。(详见 PEP 563)。
3.5.2 新版功能.
pydoc
—- 文档生成器和在线帮助系统
源代码: Lib/pydoc.py
pydoc
模块会根据 Python 模块来自动生成文档。 生成的文档可在控制台中显示为文本页面,提供给 Web 浏览器访问或者保存为 HTML 文件。
对于模块、类、函数和方法,显示的文档内容取自文档字符串(即 __doc__
属性),并会递归地从其带文档的成员中获取。 如果没有文档字符串,pydoc
会尝试从类、函数或方法定义上方,或是模块顶部的注释行段落获取
内置函数 help()
会发起调用交互式解释器的在线帮助系统,该系统使用 pydoc
在终端上生成文本形式的文档内容。 同样的文本文档也可以在 Python 解释器以外通过在操作系统的命令提示符下以脚本方式运行 pydoc 来查看。 例如,运行
pydoc sys
在终端提示符下将通过 sys
模块显示文档内容,其样式类似于 Unix man 命令所显示的指南页面。 pydoc 的参数可以为函数、模块、包,或带点号的对模块中的类、方法或函数以及包中的模块的引用。 如果传给 pydoc 的参数像是一个路径(即包含所在操作系统的路径分隔符,例如 Unix 的正斜杠),并且其指向一个现有的 Python 源文件,则会为该文件生成文档内容。
注解
为了找到对象及其文档内容,pydoc
会导入文档所在的模块。 因此,任何模块层级的代码都将被执行。 请使用 if __name__ == '__main__':
语句来确保一个文件的特定代码仅在作为脚本被发起调用时执行而不是在被导入时执行。
当打印输出到控制台时,pydoc 会尝试对输出进行分页以方便阅读。 如果设置了 PAGER
环境变量,pydoc 将使用该变量值作为分页程序。
在参数前指定 -w
旗标将把 HTML 文档写入到当前目录下的一个文件中,而不是在控制台中显示文本。
在参数前指定 -k
旗标将在全部可用模块的提要行中搜索参数所给定的关键字,具体方式同样类似于 Unix man 命令。 模块的提要行就是其文档字符串的第一行。
你还可以使用 pydoc 在本机上启动一个 HTTP 服务器并向来访的 Web 浏览器展示文档。 pydoc -p 1234 将在 1234 端口上启动 HTTP 服务器,允许在你使用 Web 浏览器通过 http://localhost:1234/
来浏览文档内容。 指定 0
作为端口号将任意选择一个未使用的端口。
pydoc -n
pydoc -b 将启动服务并额外打开一个 Web 浏览器访问模块索引页。 所发布的每个页面顶端都带有导航栏,你可以点击 Get 获取特定条目的帮助,点击 Search 在所有模块的提要行中搜索特定关键词,或是点击 Module index, Topics 和 Keywords 前往相应的页面。
当 pydoc 生成文档内容时,它会使用当前环境和路径来定位模块。 因此,发起调用 pydoc spam 得到的文档版本会与你启动 Python 解释器并输入 import spam
时得到的模块版本完全相同。
核心模块的模块文档位置对应于 https://docs.python.org/X.Y/library/
其中 X
和 Y
是 Python 解释器的主要版本号和小版本号。 这可通过设置 PYTHONDOCS
环境变量来重载为指向不同的 URL 或包含 Library Reference Manual 页面的本地目录。
在 3.2 版更改: 添加 -b
选项。
在 3.3 版更改: 命令行选项 -g
已经移除。
在 3.4 版更改: pydoc
现在会使用 inspect.signature()
而非 inspect.getfullargspec()
来从可调用对象中提取签名信息。
在 3.7 版更改: 添加 -n
选项。
Python 开发模式
doctest
—- 测试交互性的Python示例
源代码 Lib/doctest.py
doctest
模块寻找像Python交互式代码的文本,然后执行这些代码来确保它们的确就像展示的那样正确运行,有许多方法来使用doctest:
- 通过验证所有交互式示例仍然按照记录的方式工作,以此来检查模块的文档字符串是否是最新的。
- 通过验证来自一个测试文件或一个测试对象的交互式示例按预期工作,来进行回归测试。
- To write tutorial documentation for a package, liberally illustrated with input-output examples. Depending on whether the examples or the expository text are emphasized, this has the flavor of “literate testing” or “executable documentation”.
unittest
—- 单元测试框架
源代码: Lib/unittest/init.py
2to3 - 自动将 Python 2 代码转为 Python 3 代码
2to3 是一个 Python 程序,它可以读取 Python 2.x 的源代码并使用一系列的 修复器 来将其转换为合法的 Python 3.x 代码。 标准库已包含了丰富的修复器,这足以处理几乎所有代码。 不过 2to3 的支持库 lib2to3
是一个很灵活通用的库,所以还可以编写你自己的 2to3 修复器。
使用 2to3
2to3 通常会作为脚本和 Python 解释器一起安装,你可以在 Python 根目录的 Tools/scripts
文件夹下找到它。
2to3 的基本调用参数是一个需要转换的文件或目录列表。对于目录,会递归地寻找其中的 Python 源码。
这里有一个 Python 2.x 的源码文件,example.py
:
def greet(name):
print "Hello, {0}!".format(name)
print "What's your name?"
name = raw_input()
greet(name)
它可以在命令行中使用 2to3 转换成 Python 3.x 版本的代码:
$ 2to3 example.py
这个命令会打印出和源文件的区别。通过传入 -w
参数,2to3 也可以把需要的修改写回到原文件中(除非传入了 -n
参数,否则会为原始文件创建一个副本):
$ 2to3 -w example.py
在转换完成后,example.py
看起来像是这样:
def greet(name):
print("Hello, {0}!".format(name))
print("What's your name?")
name = input()
greet(name)
注释和缩进都会在转换过程中保持不变。
默认情况下,2to3 会执行 预定义修复器 的集合。使用 -l
参数可以列出所有可用的修复器。使用 -f
参数可以明确指定需要使用的修复器集合。而使用 -x
参数则可以明确指定不使用的修复器。下面的例子会只使用 imports
和 has_key
修复器运行:
$ 2to3 -f imports -f has_key example.py
这个命令会执行除了 apply
之外的所有修复器:
$ 2to3 -x apply example.py
有一些修复器是需要 显式指定 的,它们默认不会执行,必须在命令行中列出才会执行。比如下面的例子,除了默认的修复器以外,还会执行 idioms
修复器:
$ 2to3 -f all -f idioms example.py
注意这里使用 all
来启用所有默认的修复器。
有些情况下 2to3 会找到源码中有一些需要修改,但是无法自动处理的代码。在这种情况下,2to3 会在差异处下面打印一个警告信息。你应该定位到相应的代码并对其进行修改,以使其兼容 Python 3.x。
2to3 也可以重构 doctests。使用 -d
开启这个模式。需要注意只有 doctests 会被重构。这种模式下不需要文件是合法的 Python 代码。举例来说,reST 文档中类似 doctests 的示例也可以使用这个选项进行重构。
-v
选项可以输出更多转换程序的详细信息。
由于某些 print 语句可被解读为函数调用或是语句,2to3 并不总能读取包含 print 函数的文件。 当 2to3 检测到存在 from __future__ import print_function
编译器指令时,会修改其内部语法将 print()
解读为函数。 这一变动也可以使用 -p
旗标手动开启。 使用 -p
来为已转换过 print 语句的代码运行修复器。 也可以使用 -e
将 exec()
解读为函数。
-o
或 --output-dir
选项可以指定将转换后的文件写入其他目录中。由于这种情况下不会覆写原始文件,所以创建副本文件毫无意义,因此也需要使用 -n
选项来禁用创建副本。
3.2.3 新版功能: 增加了 -o
选项。
-W
或 --write-unchanged-files
选项用来告诉 2to3 始终需要输出文件,即使没有任何改动。这在使用 -o
参数时十分有用,这样就可以将整个 Python 源码包完整地转换到另一个目录。这个选项隐含了 -w
选项,否则等于没有作用。
3.2.3 新版功能: 增加了 -W
选项。
--add-suffix
选项接受一个字符串,用来作为后缀附加在输出文件名后面的后面。由于写入的文件名与原始文件不同,所以没有必要创建副本,因此 -n
选项也是必要的。举个例子:
$ 2to3 -n -W --add-suffix=3 example.py
这样会把转换后的文件写入 example.py3
文件。
3.2.3 新版功能: 增加了 --add-suffix
选项。
将整个项目从一个目录转换到另一个目录可以用这样的命令:
$ 2to3 --output-dir=python3-version/mycode -W -n python2-version/mycode
修复器
转换代码的每一个步骤都封装在修复器中。可以使用 2to3 -l
来列出可用的修复器。之前已经提到,每个修复器都可以独立地打开或是关闭。下面会对各个修复器做更详细的描述。
apply
移除对 apply()
的使用,举例来说,apply(function, *args, **kwargs)
会被转换成 function(*args, **kwargs)
。
asserts
将已弃用的 unittest
方法替换为正确的。
从 | 到 |
---|---|
failUnlessEqual(a, b) |
assertEqual(a, b) |
assertEquals(a, b) |
assertEqual(a, b) |
failIfEqual(a, b) |
assertNotEqual(a, b) |
assertNotEquals(a, b) |
assertNotEqual(a, b) |
failUnless(a) |
assertTrue(a) |
assert_(a) |
assertTrue(a) |
failIf(a) |
assertFalse(a) |
failUnlessRaises(exc, cal) |
assertRaises(exc, cal) |
failUnlessAlmostEqual(a, b) |
assertAlmostEqual(a, b) |
assertAlmostEquals(a, b) |
assertAlmostEqual(a, b) |
failIfAlmostEqual(a, b) |
assertNotAlmostEqual(a, b) |
assertNotAlmostEquals(a, b) |
assertNotAlmostEqual(a, b) |
basestring
将 basestring
转换为 str
。
buffer
将 buffer
转换为 memoryview
。这个修复器是可选的,因为 memoryview
API 和 buffer
很相似,但不完全一样。
dict
修复字典迭代方法。dict.iteritems()
会转换成 dict.items()
,dict.iterkeys()
会转换成 dict.keys()
,dict.itervalues()
会转换成 dict.values()
。类似的,dict.viewitems()
,dict.viewkeys()
和 dict.viewvalues()
会分别转换成 dict.items()
,dict.keys()
和 dict.values()
。另外也会将原有的 dict.items()
,dict.keys()
和 dict.values()
方法调用用 list
包装一层。
except
将 except X, T
转换为 except X as T
。
exec
将 exec
语句转换为 exec()
函数调用。
execfile
移除 execfile()
的使用。execfile()
的实参会使用 open()
,compile()
和 exec()
包装。
exitfunc
将对 sys.exitfunc
的赋值改为使用 atexit
模块代替。
filter
将 filter()
函数用 list
包装一层。
funcattrs
修复已经重命名的函数属性。比如 my_function.func_closure
会被转换为 my_function.__closure__
。
future
移除 from __future__ import new_feature
语句。
getcwdu
将 os.getcwdu()
重命名为 os.getcwd()
。
has_key
将 dict.has_key(key)
转换为 key in dict
。
idioms
这是一个可选的修复器,会进行多种转换,将 Python 代码变成更加常见的写法。类似 type(x) is SomeClass
和 type(x) == SomeClass
的类型对比会被转换成 isinstance(x, SomeClass)
。while 1
转换成 while True
。这个修复器还会在合适的地方使用 sorted()
函数。举个例子,这样的代码块:
L = list(some_iterable)L.sort()
会被转换为:
L = sorted(some_iterable)
import
检测 sibling imports,并将其转换成相对 import。
imports
处理标准库模块的重命名。
imports2
处理标准库中其他模块的重命名。这个修复器由于一些技术上的限制,因此和 imports
拆分开了。
input
将 input(prompt)
转换为 eval(input(prompt))
。
intern
将 intern()
转换为 sys.intern()
。
isinstance
修复 isinstance()
函数第二个实参中重复的类型。举例来说,isinstance(x, (int, int))
会转换为 isinstance(x, int)
, isinstance(x, (int, float, int))
会转换为 isinstance(x, (int, float))
。
itertools_imports
移除 itertools.ifilter()
,itertools.izip()
以及 itertools.imap()
的 import。对 itertools.ifilterfalse()
的 import 也会替换成 itertools.filterfalse()
。
itertools
修改 itertools.ifilter()
,itertools.izip()
和 itertools.imap()
的调用为对应的内建实现。itertools.ifilterfalse()
会替换成 itertools.filterfalse()
。
long
将 long
重命名为 int
。
map
用 list
包装 map()
。同时也会将 map(None, x)
替换为 list(x)
。使用 from future_builtins import map
禁用这个修复器。
metaclass
将老的元类语法(类体中的 __metaclass__ = Meta
)替换为新的(class X(metaclass=Meta)
)。
methodattrs
修复老的方法属性名。例如 meth.im_func
会被转换为 meth.__func__
。
ne
转换老的不等语法,将 <>
转为 !=
。
next
将迭代器的 next()
方法调用转为 next()
函数。也会将 next()
方法重命名为 __next__()
。
nonzero
将 __nonzero__()
转换为 __bool__()
。
numliterals
将八进制字面量转为新的语法。
operator
将 operator
模块中的许多方法调用转为其他的等效函数调用。如果有需要,会添加适当的 import
语句,比如 import collections.abc
。有以下转换映射:
从 | 到 |
---|---|
operator.isCallable(obj) |
callable(obj) |
operator.sequenceIncludes(obj) |
operator.contains(obj) |
operator.isSequenceType(obj) |
isinstance(obj, collections.abc.Sequence) |
operator.isMappingType(obj) |
isinstance(obj, collections.abc.Mapping) |
operator.isNumberType(obj) |
isinstance(obj, numbers.Number) |
operator.repeat(obj, n) |
operator.mul(obj, n) |
operator.irepeat(obj, n) |
operator.imul(obj, n) |
paren
在列表生成式中增加必须的括号。例如将 [x for x in 1, 2]
转换为 [x for x in (1, 2)]
。
print
将 print
语句转换为 print()
函数。
raise
将 raise E, V
转换为 raise E(V)
,将 raise E, V, T
转换为 raise E(V).with_traceback(T)
。如果 E
是元组,这样的转换是不正确的,因为用元组代替异常的做法在 3.0 中已经移除了。
raw_input
将 raw_input()
转换为 input()
。
reduce
将 reduce()
转换为 functools.reduce()
。
reload
将 reload()
转换为 importlib.reload()
。
renames
将 sys.maxint
转换为 sys.maxsize
。
repr
将反引号 repr 表达式替换为 repr()
函数。
set_literal
将 set
构造函数替换为 set literals 写法。这个修复器是可选的。
standarderror
将 StandardError
重命名为 Exception
。
sys_exc
将弃用的 sys.exc_value
,sys.exc_type
,sys.exc_traceback
替换为 sys.exc_info()
的用法。
throw
修复生成器的 throw()
方法的 API 变更。
tuple_params
移除隐式的元组参数解包。这个修复器会插入临时变量。
types
修复 type
模块中一些成员的移除引起的代码问题。
unicode
将 unicode
重命名为 str
。
urllib
将 urllib
和 urllib2
重命名为 urllib
包。
ws_comma
移除逗号分隔的元素之间多余的空白。这个修复器是可选的。
xrange
将 xrange()
重命名为 range()
,并用 list
包装原有的 range()
。
xreadlines
将 for x in file.xreadlines()
转换为 for x in file
。
zip
用 list
包装 zip()
。如果使用了 from future_builtins import zip
的话会禁用。
lib2to3
—— 2to3 支持库
源代码: Lib/lib2to3/
Deprecated since version 3.11, will be removed in version 3.13: Python 3.9 switched to a PEG parser (see PEP 617) while lib2to3 is using a less flexible LL(1) parser. Python 3.10 includes new language syntax that is not parsable by lib2to3’s LL(1) parser (see PEP 634). The lib2to3
module was marked pending for deprecation in Python 3.9 (raising PendingDeprecationWarning
on import) and fully deprecated in Python 3.11 (raising DeprecationWarning
). It will be removed from the standard library in Python 3.13. Consider third-party alternatives such as LibCST or parso.
注解
lib2to3
API 并不稳定,并可能在未来大幅修改。
test
—- Python回归测试包
test
— Python回归测试包test.support
— Utilities for the Python test suitetest.support.socket_helper
— Utilities for socket teststest.support.script_helper
— Utilities for the Python execution teststest.support.bytecode_helper
— Support tools for testing correct bytecode generationtest.support.threading_helper
— Utilities for threading teststest.support.os_helper
— Utilities for os teststest.support.import_helper
— Utilities for import teststest.support.warnings_helper
— Utilities for warnings tests
调试和分析
这些库可以帮助你进行 Python 开发:调试器使你能够逐步执行代码,分析堆栈帧并设置中断点等等,性能分析器可以运行代码并为你提供执行时间的详细数据,使你能够找出你的程序中的瓶颈。 审计事件提供运行时行为的可见性,如果没有此工具则需要进行侵入式调试或修补。
- 审计事件表
bdb
— Debugger frameworkfaulthandler
—— 转储 Python 的跟踪信息pdb
— Python 的调试器- Python Profilers 分析器
timeit
— 测量小代码片段的执行时间trace
—— 跟踪 Python 语句的执行tracemalloc
— 跟踪内存分配
审计事件表
下表包含了在整个 CPython 运行时和标准库中由 sys.audit()
或 PySys_Audit()
调用所引发的全部事件。 这些调用是在 3.8.0 或更高版本中添加了 (参见 PEP 578)。
请参阅 sys.addaudithook()
和 PySys_AddAuditHook()
了解有关处理这些事件的详细信息。
CPython implementation detail: 此表是根据 CPython 文档生成的,可能无法表示其他实现所引发的事件。 请参阅你的运行时专属的文档了解实际引发的事件。
Audit event | Arguments | References |
---|---|---|
array.new | typecode , initializer |
[1] |
builtins.breakpoint | breakpointhook |
[1] |
builtins.id | id |
[1] |
builtins.input | prompt |
[1] |
builtins.input/result | result |
[1] |
code.new | code , filename , name , argcount , posonlyargcount , kwonlyargcount , nlocals , stacksize , flags |
[1] |
compile | source , filename |
[1] |
cpython.PyInterpreterState_Clear | [1] | |
cpython.PyInterpreterState_New | [1] | |
cpython._PySys_ClearAuditHooks | [1] | |
cpython.run_command | command |
[1] |
cpython.run_file | filename |
[1] |
cpython.run_interactivehook | hook |
[1] |
cpython.run_module | module-name |
[1] |
cpython.run_startup | filename |
[1] |
cpython.run_stdin | [1] | |
ctypes.addressof | obj |
[1] |
ctypes.call_function | func_pointer , arguments |
[1] |
ctypes.cdata | address |
[1] |
ctypes.cdata/buffer | pointer , size , offset |
[1][2] |
ctypes.create_string_buffer | init , size |
[1] |
ctypes.create_unicode_buffer | init , size |
[1] |
ctypes.dlopen | name |
[1] |
ctypes.dlsym | library , name |
[1] |
ctypes.dlsym/handle | handle , name |
[1] |
ctypes.get_errno | [1] | |
ctypes.get_last_error | [1] | |
ctypes.seh_exception | code |
[1] |
ctypes.set_errno | errno |
[1] |
ctypes.set_last_error | error |
[1] |
ctypes.string_at | address , size |
[1] |
ctypes.wstring_at | address , size |
[1] |
ensurepip.bootstrap | root |
[1] |
exec | code_object |
[1][2] |
fcntl.fcntl | fd , cmd , arg |
[1] |
fcntl.flock | fd , operation |
[1] |
fcntl.ioctl | fd , request , arg |
[1] |
fcntl.lockf | fd , cmd , len , start , whence |
[1] |
ftplib.connect | self , host , port |
[1] |
ftplib.sendcmd | self , cmd |
[1][2] |
function.new | code |
[1] |
gc.get_objects | generation |
[1] |
gc.get_referents | objs |
[1] |
gc.get_referrers | objs |
[1] |
glob.glob | pathname , recursive |
[1][2] |
glob.glob/2 | pathname , recursive , root_dir , dir_fd |
[1][2] |
http.client.connect | self , host , port |
[1] |
http.client.send | self , data |
[1] |
imaplib.open | self , host , port |
[1] |
imaplib.send | self , data |
[1] |
import | module , filename , sys.path , sys.meta_path , sys.path_hooks |
[1] |
marshal.dumps | value , version |
[1] |
marshal.load | [1] | |
marshal.loads | bytes |
[1] |
mmap.new | fileno , length , access , offset |
[1] |
msvcrt.get_osfhandle | fd |
[1] |
msvcrt.locking | fd , mode , nbytes |
[1] |
msvcrt.open_osfhandle | handle , flags |
[1] |
nntplib.connect | self , host , port |
[1][2] |
nntplib.putline | self , line |
[1][2] |
object.delattr | obj , name |
[1] |
object.getattr | obj , name |
[1] |
object.setattr | obj , name , value |
[1] |
open | path , mode , flags |
[1][2][3] |
os.add_dll_directory | path |
[1] |
os.chdir | path |
[1][2] |
os.chflags | path , flags |
[1][2] |
os.chmod | path , mode , dir_fd |
[1][2][3] |
os.chown | path , uid , gid , dir_fd |
[1][2][3] |
os.exec | path , args , env |
[1] |
os.fork | [1] | |
os.forkpty | [1] | |
os.fwalk | top , topdown , onerror , follow_symlinks , dir_fd |
[1] |
os.getxattr | path , attribute |
[1] |
os.kill | pid , sig |
[1] |
os.killpg | pgid , sig |
[1] |
os.link | src , dst , src_dir_fd , dst_dir_fd |
[1] |
os.listdir | path |
[1] |
os.listxattr | path |
[1] |
os.lockf | fd , cmd , len |
[1] |
os.mkdir | path , mode , dir_fd |
[1][2] |
os.posix_spawn | path , argv , env |
[1][2] |
os.putenv | key , value |
[1] |
os.remove | path , dir_fd |
[1][2][3] |
os.removexattr | path , attribute |
[1] |
os.rename | src , dst , src_dir_fd , dst_dir_fd |
[1][2][3] |
os.rmdir | path , dir_fd |
[1] |
os.scandir | path |
[1] |
os.setxattr | path , attribute , value , flags |
[1] |
os.spawn | mode , path , args , env |
[1] |
os.startfile | path , operation |
[1] |
os.startfile/2 | path , operation , arguments , cwd , show_cmd |
[1] |
os.symlink | src , dst , dir_fd |
[1] |
os.system | command |
[1] |
os.truncate | fd , length |
[1][2] |
os.unsetenv | key |
[1] |
os.utime | path , times , ns , dir_fd |
[1] |
os.walk | top , topdown , onerror , followlinks |
[1] |
pathlib.Path.glob | self , pattern |
[1] |
pathlib.Path.rglob | self , pattern |
[1] |
pdb.Pdb | [1] | |
pickle.find_class | module , name |
[1] |
poplib.connect | self , host , port |
[1][2] |
poplib.putline | self , line |
[1][2] |
pty.spawn | argv |
[1] |
resource.prlimit | pid , resource , limits |
[1] |
resource.setrlimit | resource , limits |
[1] |
setopencodehook | [1] | |
shutil.chown | path , user , group |
[1] |
shutil.copyfile | src , dst |
[1][2][3] |
shutil.copymode | src , dst |
[1][2] |
shutil.copystat | src , dst |
[1][2] |
shutil.copytree | src , dst |
[1] |
shutil.make_archive | base_name , format , root_dir , base_dir |
[1] |
shutil.move | src , dst |
[1] |
shutil.rmtree | path |
[1] |
shutil.unpack_archive | filename , extract_dir , format |
[1] |
signal.pthread_kill | thread_id , signalnum |
[1] |
smtplib.connect | self , host , port |
[1] |
smtplib.send | self , data |
[1] |
socket.new | self , family , type , protocol |
[1] |
socket.bind | self , address |
[1] |
socket.connect | self , address |
[1][2] |
socket.getaddrinfo | host , port , family , type , protocol |
[1] |
socket.gethostbyaddr | ip_address |
[1] |
socket.gethostbyname | hostname |
[1][2] |
socket.gethostname | [1] | |
socket.getnameinfo | sockaddr |
[1] |
socket.getservbyname | servicename , protocolname |
[1] |
socket.getservbyport | port , protocolname |
[1] |
socket.sendmsg | self , address |
[1] |
socket.sendto | self , address |
[1] |
socket.sethostname | name |
[1] |
sqlite3.connect | database |
[1] |
sqlite3.connect/handle | connection_handle |
[1] |
sqlite3.enable_load_extension | connection , enabled |
[1] |
sqlite3.load_extension | connection , path |
[1] |
subprocess.Popen | executable , args , cwd , env |
[1] |
sys._current_exceptions | [1] | |
sys._current_frames | [1] | |
sys._getframe | [1] | |
sys.addaudithook | [1][2] | |
sys.excepthook | hook , type , value , traceback |
[1] |
sys.set_asyncgen_hooks_finalizer | [1] | |
sys.set_asyncgen_hooks_firstiter | [1] | |
sys.setprofile | [1] | |
sys.settrace | [1] | |
sys.unraisablehook | hook , unraisable |
[1] |
syslog.closelog | [1] | |
syslog.openlog | ident , logoption , facility |
[1] |
syslog.setlogmask | maskpri |
[1] |
syslog.syslog | priority , message |
[1] |
telnetlib.Telnet.open | self , host , port |
[1] |
telnetlib.Telnet.write | self , buffer |
[1] |
tempfile.mkdtemp | fullpath |
[1][2] |
tempfile.mkstemp | fullpath |
[1][2][3] |
urllib.Request | fullurl , data , headers , method |
[1] |
webbrowser.open | url |
[1] |
winreg.ConnectRegistry | computer_name , key |
[1] |
winreg.CreateKey | key , sub_key , access |
[1][2] |
winreg.DeleteKey | key , sub_key , access |
[1][2] |
winreg.DeleteValue | key , value |
[1] |
winreg.DisableReflectionKey | key |
[1] |
winreg.EnableReflectionKey | key |
[1] |
winreg.EnumKey | key , index |
[1] |
winreg.EnumValue | key , index |
[1] |
winreg.ExpandEnvironmentStrings | str |
[1] |
winreg.LoadKey | key , sub_key , file_name |
[1] |
winreg.OpenKey | key , sub_key , access |
[1] |
winreg.OpenKey/result | key |
[1][2][3] |
winreg.PyHKEY.Detach | key |
[1] |
winreg.QueryInfoKey | key |
[1] |
winreg.QueryReflectionKey | key |
[1] |
winreg.QueryValue | key , sub_key , value_name |
[1][2] |
winreg.SaveKey | key , file_name |
[1] |
winreg.SetValue | key , sub_key , type , value |
[1][2] |
下列事件只在内部被引发,而不会回应任何 CPython 公共 API:
审计事件 | 实参 |
---|---|
_winapi.CreateFile | file_name , desired_access , share_mode , creation_disposition , flags_and_attributes |
_winapi.CreateJunction | src_path , dst_path |
_winapi.CreateNamedPipe | name , open_mode , pipe_mode |
_winapi.CreatePipe | |
_winapi.CreateProcess | application_name , command_line , current_directory |
_winapi.OpenProcess | process_id , desired_access |
_winapi.TerminateProcess | handle , exit_code |
ctypes.PyObj_FromPtr | obj |
软件打包和分发
这些库可帮助你发布和安装 Python 软件。 虽然这些模块设计为与Python 包索引 <[https://pypi.org](https://pypi.org/)>
__结合使用,但它们也可以与本地索引服务器一起使用,或者根本不使用任何索引服务器。
distutils
—- 构建和安装 Python 模块ensurepip
—- Bootstrapping thepip
installer- Command line interface
- Module API
venv
—- 创建虚拟环境- 创建虚拟环境
- API
- 一个扩展
EnvBuilder
的例子
zipapp
—- Manage executable Python zip archives- Basic Example
- 命令行接口
- Python API
- 例子
- Specifying the Interpreter
- Creating Standalone Applications with zipapp
- Making a Windows executable
- Caveats
- The Python Zip Application Archive Format
distutils
—- 构建和安装 Python 模块
distutils
已被弃用并计划在 Python 3.12 中移除。
distutils
包为将待构建和安装的额外的模块,打包成 Python 安装包提供支持。新模块既可以是百分百的纯 Python,也可以是用 C 写的扩展模块,或者可以是一组包含了同时用 Python 和 C 编码的 Python 包。
大多数 Python 用户 不会 想要直接使用这个包,而是使用 Python 包官方维护的跨版本工具。特别地, setuptools 是一个对于 distutils
的增强选项,它能提供:
- 对声明项目依赖的支持
- 额外的用于配置哪些文件包含在源代码发布中的机制(包括与版本控制系统集成需要的插件)
- 生成项目“进入点”的能力,进入点可用作应用插件系统的基础
- 自动在安装时间生成 Windows 命令行可执行文件的能力,而不是需要预编译它们
- 跨所有受支持的 Python 版本上的一致的表现
推荐的 pip 安装器用 setuptools
运行所有的 setup.py
脚本,即使脚本本身只引了 distutils
包。
为了打包工具的作者和用户能更好理解当前的打包和分发系统,遗留的基于 distutils
的用户文档和 API 参考保持可用:
ensurepip
—- Bootstrapping the pip
installer
3.4 新版功能.
The ensurepip
package provides support for bootstrapping the pip
installer into an existing Python installation or virtual environment. This bootstrapping approach reflects the fact that pip
is an independent project with its own release cycle, and the latest available stable version is bundled with maintenance and feature releases of the CPython reference interpreter.
In most cases, end users of Python shouldn’t need to invoke this module directly (as pip
should be bootstrapped by default), but it may be needed if installing pip
was skipped when installing Python (or when creating a virtual environment) or after explicitly uninstalling pip
.
注解
This module does not access the internet. All of the components needed to bootstrap pip
are included as internal parts of the package.
Command line interface
The command line interface is invoked using the interpreter’s -m
switch.
The simplest possible invocation is:
python -m ensurepip
This invocation will install pip
if it is not already installed, but otherwise does nothing. To ensure the installed version of pip
is at least as recent as the one available in ensurepip
, pass the --upgrade
option:
python -m ensurepip --upgrade
By default, pip
is installed into the current virtual environment (if one is active) or into the system site packages (if there is no active virtual environment). The installation location can be controlled through two additional command line options:
--root <dir>
: Installspip
relative to the given root directory rather than the root of the currently active virtual environment (if any) or the default root for the current Python installation.--user
: Installspip
into the user site packages directory rather than globally for the current Python installation (this option is not permitted inside an active virtual environment).
By default, the scripts pipX
and pipX.Y
will be installed (where X.Y stands for the version of Python used to invoke ensurepip
). The scripts installed can be controlled through two additional command line options:
--altinstall
: if an alternate installation is requested, thepipX
script will not be installed.--default-pip
: if a “default pip” installation is requested, thepip
script will be installed in addition to the two regular scripts.
Providing both of the script selection options will trigger an exception.
Module API
ensurepip
exposes two functions for programmatic use:
ensurepip.version
()
Returns a string specifying the available version of pip that will be installed when bootstrapping an environment.
ensurepip.bootstrap
(root=None, upgrade=False, user=False, altinstall=False, default_pip=False, verbosity=0)
Bootstraps pip
into the current or designated environment.
root specifies an alternative root directory to install relative to. If root is None
, then installation uses the default install location for the current environment.
upgrade indicates whether or not to upgrade an existing installation of an earlier version of pip
to the available version.
user indicates whether to use the user scheme rather than installing globally.
By default, the scripts pipX
and pipX.Y
will be installed (where X.Y stands for the current version of Python).
If altinstall is set, then pipX
will not be installed.
If default_pip is set, then pip
will be installed in addition to the two regular scripts.
Setting both altinstall and default_pip will trigger ValueError
.
verbosity controls the level of output to sys.stdout
from the bootstrapping operation.
Raises an auditing event ensurepip.bootstrap
with argument root
.
注解
The bootstrapping process has side effects on both sys.path
and os.environ
. Invoking the command line interface in a subprocess instead allows these side effects to be avoided.
注解
The bootstrapping process may install additional modules required by pip
, but other software should not assume those dependencies will always be present by default (as the dependencies may be removed in a future version of pip
).
venv
—- 创建虚拟环境
3.3 新版功能.
源码: Lib/venv/
venv
模块支持使用自己的站点目录创建轻量级“虚拟环境”,可选择与系统站点目录隔离。每个虚拟环境都有自己的 Python 二进制文件(与用于创建此环境的二进制文件的版本相匹配),并且可以在其站点目录中拥有自己独立的已安装 Python 软件包集。
有关 Python 虚拟环境的更多信息,请参阅 PEP 405 。
参见
创建虚拟环境
通过执行 venv
指令来创建一个 虚拟环境:
python3 -m venv /path/to/new/virtual/environment
运行此命令将创建目标目录(父目录若不存在也将创建),并放置一个 pyvenv.cfg
文件在其中,文件中有一个 home
键,它的值指向运行此命令的 Python 安装(目标目录的常用名称是 .venv
)。它还会创建一个 bin
子目录(在 Windows 上是 Scripts
),其中包含 Python 二进制文件的副本或符号链接(视创建环境时使用的平台或参数而定)。它还会创建一个(初始为空的) lib/pythonX.Y/site-packages
子目录(在 Windows 上是 Lib\site-packages
)。如果指定了一个现有的目录,这个目录就将被重新使用。
3.6 版后已移除: pyvenv
是 Python 3.3 和 3.4 中创建虚拟环境的推荐工具,不过 在 Python 3.6 中已弃用。
在 3.5 版更改: 现在推荐使用 venv
来创建虚拟环境。
在 Windows 上,调用 venv
命令如下:
c:\>c:\Python35\python -m venv c:\path\to\myenv
或者,如果已经为 Python 安装 配置好 PATH
和 PATHEXT
变量:
c:\>python -m venv c:\path\to\myenv
本命令如果以 -h
参数运行,将显示可用的选项:
usage: venv [-h] [--system-site-packages] [--symlinks | --copies] [--clear]
[--upgrade] [--without-pip] [--prompt PROMPT] [--upgrade-deps]
ENV_DIR [ENV_DIR ...]
Creates virtual Python environments in one or more target directories.
positional arguments:
ENV_DIR A directory to create the environment in.
optional arguments:
-h, --help show this help message and exit
--system-site-packages
Give the virtual environment access to the system
site-packages dir.
--symlinks Try to use symlinks rather than copies, when symlinks
are not the default for the platform.
--copies Try to use copies rather than symlinks, even when
symlinks are the default for the platform.
--clear Delete the contents of the environment directory if it
already exists, before environment creation.
--upgrade Upgrade the environment directory to use this version
of Python, assuming Python has been upgraded in-place.
--without-pip Skips installing or upgrading pip in the virtual
environment (pip is bootstrapped by default)
--prompt PROMPT Provides an alternative prompt prefix for this
environment.
--upgrade-deps Upgrade core dependencies: pip setuptools to the
latest version in PyPI
Once an environment has been created, you may wish to activate it, e.g. by
sourcing an activate script in its bin directory.
在 3.9 版更改: 添加 --upgrade-deps
选项,用于将 pip + setuptools 升级到 PyPI 上的最新版本
在 3.4 版更改: 默认安装 pip,并添加 --without-pip
和 --copies
选项
在 3.4 版更改: 在早期版本中,如果目标目录已存在,将引发错误,除非使用了 --clear
或 --upgrade
选项。
注解
虽然 Windows 支持符号链接,但不推荐使用它们。特别注意,在文件资源管理器中双击 python.exe
将立即解析符号链接,并忽略虚拟环境。
注解
在 Microsoft Windows 上,为了启用 Activate.ps1
脚本,可能需要修改用户的执行策略。可以运行以下 PowerShell 命令来执行此操作:
PS C:> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
参阅 About Execution Policies 以获取更多信息。
生成的 pyvenv.cfg
文件还包括 include-system-site-packages
键,如果运行 venv
时带有 --system-site-packages
选项,则键值为 true
,否则为 false
。
除非采用 --without-pip
选项,否则将会调用 ensurepip
将 pip
引导到虚拟环境中。
可以向 venv
传入多个路径,此时将根据给定的选项,在所给的每个路径上创建相同的虚拟环境。
创建虚拟环境后,可以使用虚拟环境的二进制目录中的脚本来“激活”该环境。不同平台调用的脚本是不同的(须将
平台 | Shell | 用于激活虚拟环境的命令 |
---|---|---|
POSIX | bash/zsh | $ source <venv>/bin/activate |
fish | $ source <venv>/bin/activate.fish | |
csh/tcsh | $ source <venv>/bin/activate.csh | |
PowerShell Core | $ <venv>/bin/Activate.ps1 | |
Windows | cmd.exe | C:> <venv>\Scripts\activate.bat |
PowerShell | PS C:> <venv>\Scripts\Activate.ps1 |
当一个虚拟环境被激活时,VIRTUAL_ENV
环境变量会被设为该虚拟环境的路径。 这可被用来检测程序是否运行在虚拟环境中。
激活环境不是 必须 的,激活只是将虚拟环境的二进制目录添加到搜索路径中,这样 “python” 命令将调用虚拟环境的 Python 解释器,可以运行其中已安装的脚本,而不必输入其完整路径。但是,安装在虚拟环境中的所有脚本都应在不激活的情况下可运行,并自动与虚拟环境的 Python 一起运行。
在 shell 中输入 “deactivate” 可以退出虚拟环境。具体机制取决于不同平台,并且是内部实现(通常使用脚本或 shell 函数)。
3.4 新版功能: fish
和 csh
激活脚本。
3.8 新版功能: 在 POSIX 上安装 PowerShell 激活脚本,以支持 PowerShell Core。
注解
虚拟环境是一个 Python 环境,安装到其中的 Python 解释器、库和脚本与其他虚拟环境中的内容是隔离的,且(默认)与“系统级” Python(操作系统的一部分)中安装的库是隔离的。
虚拟环境是一个目录树,其中包含 Python 可执行文件和其他文件,其他文件指示了这是一个是虚拟环境。
常用安装工具如 setuptools 和 pip 可以在虚拟环境中按预期工作。换句话说,当虚拟环境被激活,它们就会将 Python 软件包安装到虚拟环境中,无需明确指示。
当虚拟环境被激活(即虚拟环境的 Python 解释器正在运行),属性 sys.prefix
和 sys.exec_prefix
指向的是虚拟环境的基础目录,而 sys.base_prefix
和 sys.base_exec_prefix
指向非虚拟环境的 Python 安装,即曾用于创建虚拟环境的那个 Python 安装。如果虚拟环境没有被激活,则 sys.prefix
与 sys.base_prefix
相同,且 sys.exec_prefix
与 sys.base_exec_prefix
相同(它们均指向非虚拟环境的 Python 安装)。
当虚拟环境被激活,所有 distutils
配置文件中更改安装路径的选项都会被忽略,以防止无意中将项目安装在虚拟环境之外。
在命令行 shell 中工作时,用户可以运行虚拟环境可执行文件目录中的 activate
脚本来激活虚拟环境(调用该文件的确切文件名和命令取决于 shell),这会将虚拟环境的可执行文件目录添加到当前 shell 的 PATH
环境变量。在其他情况下,无需激活虚拟环境。安装到虚拟环境中的脚本有 “shebang” 行,指向虚拟环境的 Python 解释器。这意味着无论 PATH
的值如何,脚本都将与该解释器一起运行。在 Windows 上,如果已安装 Python Launcher for Windows,则支持处理 “shebang” 行(此功能在 Python 3.3 中添加,详情请参阅 PEP 397)。这样,在 Windows 资源管理器中双击已安装的脚本,应该会使用正确的解释器运行该脚本,而在 PATH
中无需指向其虚拟环境。
API
上述的高级方法使用了一个简单的 API,该 API 提供了一种机制,第三方虚拟环境创建者可以根据其需求自定义环境创建过程,该 API 为 EnvBuilder
类。
class venv.EnvBuilder
(system_site_packages=False, clear=False, symlinks=False, upgrade=False, with_pip=False, prompt=None, upgrade_deps=False)
EnvBuilder
类在实例化时接受以下关键字参数:
system_site_packages
— 一个布尔值,要求系统 Python 的 site-packages 对环境可用(默认为False
)。clear
— 一个布尔值,如果为 true,则在创建环境前将删除目标目录的现有内容。symlinks
— 一个布尔值,指示是否尝试符号链接 Python 二进制文件,而不是进行复制。upgrade
— 一个布尔值,如果为 true,则将使用当前运行的 Python 去升级一个现有的环境,这主要在原位置的 Python 更新后使用(默认为False
)。with_pip
— 一个布尔值,如果为 true,则确保在虚拟环境中已安装 pip。这使用的是带有--default-pip
选项的ensurepip
。prompt
— 激活虚拟环境后显示的提示符(默认为None
,表示使用环境所在的目录名称)。如果使用了"."
这一特殊字符串,则使用当前目录的基本名称作为提示符。upgrade_deps
— 将基本 venv 模块更新为 PyPI 上的最新版本。
在 3.4 版更改: 添加 with_pip
参数
3.6 新版功能: 添加 prompt
参数
3.9 新版功能: 添加 upgrade_deps
参数
第三方虚拟环境工具的创建者可以自由地将此处提供的 EnvBuilder
类作为基类。
返回的 env-builder 是一个对象,包含一个 create
方法:
create
(env_dir)指定要建立虚拟环境的目标目录(绝对路径或相对于当前路径)来创建虚拟环境。
create
方法将在指定目录中创建环境,或者引发对应的异常。EnvBuilder
类的create
方法定义了可用于定制子类的钩子:def create(self, env_dir): """ Create a virtualized Python environment in a directory. env_dir is the target directory to create an environment in. """ env_dir = os.path.abspath(env_dir) context = self.ensure_directories(env_dir) self.create_configuration(context) self.setup_python(context) self.setup_scripts(context) self.post_setup(context)
每个方法
ensure_directories()
,create_configuration()
,setup_python()
,setup_scripts()
和post_setup()
都可以被重写。ensure_directories
(env_dir)创建环境目录和所有必需的目录,并返回一个上下文对象。该对象只是一个容器,保存属性(如路径),供其他方法使用。允许目录已经存在,如果指定了
clear
或upgrade
就允许在现有环境目录上进行操作。create_configuration
(context)在环境中创建
pyvenv.cfg
配置文件。setup_python
(context)在环境中创建 Python 可执行文件的拷贝或符号链接。在 POSIX 系统上,如果给定了可执行文件
python3.x
,将创建指向该可执行文件的python
和python3
符号链接,除非相同名称的文件已经存在。setup_scripts
(context)将适用于平台的激活脚本安装到虚拟环境中。
upgrade_dependencies
(context)升级环境中 venv 依赖的核心软件包(当前为
pip
和setuptools
)。通过在环境中使用pip
可执行文件来完成。3.9 新版功能.
post_setup
(context)占位方法,可以在第三方实现中重写,用于在虚拟环境中预安装软件包,或是其他创建后要执行的步骤。
在 3.7.2 版更改: Windows 现在为 python[w].exe
使用重定向脚本,而不是复制实际的二进制文件。仅在 3.7.2 中,除非运行的是源码树中的构建,否则 setup_python()
不会执行任何操作。
在 3.7.3 版更改: Windows 将重定向脚本复制为 setup_python()
的一部分而非 setup_scripts()
。在 3.7.2 中不是这种情况。使用符号链接时,将链接至原始可执行文件。
此外,EnvBuilder
提供了如下实用方法,可以从子类的 setup_scripts()
或 post_setup()
调用,用来将自定义脚本安装到虚拟环境中。
install_scripts
(context, path)path 是一个目录的路径,该目录应包含子目录 “common”, “posix”, “nt”,每个子目录存有发往对应环境中 bin 目录的脚本。在下列占位符替换完毕后,将复制 “common” 的内容和与
os.name
对应的子目录:__VENV_DIR__
会被替换为环境目录的绝对路径。__VENV_NAME__
会被替换为环境名称(环境目录的最后一个字段)。__VENV_PROMPT__
会被替换为提示符(用括号括起来的环境名称紧跟着一个空格)。__VENV_BIN_NAME__
会被替换为 bin 目录的名称(bin
或Scripts
)。__VENV_PYTHON__
会被替换为环境可执行文件的绝对路径。
允许目录已存在(用于升级现有环境时)。
有一个方便实用的模块级别的函数:
venv.create
(env_dir, system_site_packages=False, clear=False, symlinks=False, with_pip=False, prompt=None, upgrade_deps=False)
通过关键词参数来创建一个 EnvBuilder
,并且使用 env_dir 参数来调用它的 create()
方法。
3.3 新版功能.
在 3.4 版更改: 添加 with_pip
参数
在 3.6 版更改: 添加 prompt
参数
在 3.9 版更改: 添加 upgrade_deps
参数
一个扩展 EnvBuilder
的例子
下面的脚本展示了如何通过实现一个子类来扩展 EnvBuilder
。这个子类会安装 setuptotols 和 pip 的到被创建的虚拟环境中。
import os
import os.path
from subprocess import Popen, PIPE
import sys
from threading import Thread
from urllib.parse import urlparse
from urllib.request import urlretrieve
import venv
class ExtendedEnvBuilder(venv.EnvBuilder):
"""
This builder installs setuptools and pip so that you can pip or
easy_install other packages into the created virtual environment.
:param nodist: If true, setuptools and pip are not installed into the
created virtual environment.
:param nopip: If true, pip is not installed into the created
virtual environment.
:param progress: If setuptools or pip are installed, the progress of the
installation can be monitored by passing a progress
callable. If specified, it is called with two
arguments: a string indicating some progress, and a
context indicating where the string is coming from.
The context argument can have one of three values:
'main', indicating that it is called from virtualize()
itself, and 'stdout' and 'stderr', which are obtained
by reading lines from the output streams of a subprocess
which is used to install the app.
If a callable is not specified, default progress
information is output to sys.stderr.
"""
def __init__(self, *args, **kwargs):
self.nodist = kwargs.pop('nodist', False)
self.nopip = kwargs.pop('nopip', False)
self.progress = kwargs.pop('progress', None)
self.verbose = kwargs.pop('verbose', False)
super().__init__(*args, **kwargs)
def post_setup(self, context):
"""
Set up any packages which need to be pre-installed into the
virtual environment being created.
:param context: The information for the virtual environment
creation request being processed.
"""
os.environ['VIRTUAL_ENV'] = context.env_dir
if not self.nodist:
self.install_setuptools(context)
# Can't install pip without setuptools
if not self.nopip and not self.nodist:
self.install_pip(context)
def reader(self, stream, context):
"""
Read lines from a subprocess' output stream and either pass to a progress
callable (if specified) or write progress information to sys.stderr.
"""
progress = self.progress
while True:
s = stream.readline()
if not s:
break
if progress is not None:
progress(s, context)
else:
if not self.verbose:
sys.stderr.write('.')
else:
sys.stderr.write(s.decode('utf-8'))
sys.stderr.flush()
stream.close()
def install_script(self, context, name, url):
_, _, path, _, _, _ = urlparse(url)
fn = os.path.split(path)[-1]
binpath = context.bin_path
distpath = os.path.join(binpath, fn)
# Download script into the virtual environment's binaries folder
urlretrieve(url, distpath)
progress = self.progress
if self.verbose:
term = '\n'
else:
term = ''
if progress is not None:
progress('Installing %s ...%s' % (name, term), 'main')
else:
sys.stderr.write('Installing %s ...%s' % (name, term))
sys.stderr.flush()
# Install in the virtual environment
args = [context.env_exe, fn]
p = Popen(args, stdout=PIPE, stderr=PIPE, cwd=binpath)
t1 = Thread(target=self.reader, args=(p.stdout, 'stdout'))
t1.start()
t2 = Thread(target=self.reader, args=(p.stderr, 'stderr'))
t2.start()
p.wait()
t1.join()
t2.join()
if progress is not None:
progress('done.', 'main')
else:
sys.stderr.write('done.\n')
# Clean up - no longer needed
os.unlink(distpath)
def install_setuptools(self, context):
"""
Install setuptools in the virtual environment.
:param context: The information for the virtual environment
creation request being processed.
"""
url = 'https://bitbucket.org/pypa/setuptools/downloads/ez_setup.py'
self.install_script(context, 'setuptools', url)
# clear up the setuptools archive which gets downloaded
pred = lambda o: o.startswith('setuptools-') and o.endswith('.tar.gz')
files = filter(pred, os.listdir(context.bin_path))
for f in files:
f = os.path.join(context.bin_path, f)
os.unlink(f)
def install_pip(self, context):
"""
Install pip in the virtual environment.
:param context: The information for the virtual environment
creation request being processed.
"""
url = 'https://bootstrap.pypa.io/get-pip.py'
self.install_script(context, 'pip', url)
def main(args=None):
compatible = True
if sys.version_info < (3, 3):
compatible = False
elif not hasattr(sys, 'base_prefix'):
compatible = False
if not compatible:
raise ValueError('This script is only for use with '
'Python 3.3 or later')
else:
import argparse
parser = argparse.ArgumentParser(prog=__name__,
description='Creates virtual Python '
'environments in one or '
'more target '
'directories.')
parser.add_argument('dirs', metavar='ENV_DIR', nargs='+',
help='A directory in which to create the '
'virtual environment.')
parser.add_argument('--no-setuptools', default=False,
action='store_true', dest='nodist',
help="Don't install setuptools or pip in the "
"virtual environment.")
parser.add_argument('--no-pip', default=False,
action='store_true', dest='nopip',
help="Don't install pip in the virtual "
"environment.")
parser.add_argument('--system-site-packages', default=False,
action='store_true', dest='system_site',
help='Give the virtual environment access to the '
'system site-packages dir.')
if os.name == 'nt':
use_symlinks = False
else:
use_symlinks = True
parser.add_argument('--symlinks', default=use_symlinks,
action='store_true', dest='symlinks',
help='Try to use symlinks rather than copies, '
'when symlinks are not the default for '
'the platform.')
parser.add_argument('--clear', default=False, action='store_true',
dest='clear', help='Delete the contents of the '
'virtual environment '
'directory if it already '
'exists, before virtual '
'environment creation.')
parser.add_argument('--upgrade', default=False, action='store_true',
dest='upgrade', help='Upgrade the virtual '
'environment directory to '
'use this version of '
'Python, assuming Python '
'has been upgraded '
'in-place.')
parser.add_argument('--verbose', default=False, action='store_true',
dest='verbose', help='Display the output '
'from the scripts which '
'install setuptools and pip.')
options = parser.parse_args(args)
if options.upgrade and options.clear:
raise ValueError('you cannot supply --upgrade and --clear together.')
builder = ExtendedEnvBuilder(system_site_packages=options.system_site,
clear=options.clear,
symlinks=options.symlinks,
upgrade=options.upgrade,
nodist=options.nodist,
nopip=options.nopip,
verbose=options.verbose)
for d in options.dirs:
builder.create(d)
if __name__ == '__main__':
rc = 1
try:
main()
rc = 0
except Exception as e:
print('Error: %s' % e, file=sys.stderr)
sys.exit(rc)
zipapp
—- Manage executable Python zip archives
3.5 新版功能.
Source code: Lib/zipapp.py
This module provides tools to manage the creation of zip files containing Python code, which can be executed directly by the Python interpreter. The module provides both a 命令行接口 and a Python API.
Basic Example
The following example shows how the 命令行接口 can be used to create an executable archive from a directory containing Python code. When run, the archive will execute the main
function from the module myapp
in the archive.
$ python -m zipapp myapp -m "myapp:main"
$ python myapp.pyz
<output from myapp>
命令行接口
When called as a program from the command line, the following form is used:
$ python -m zipapp source [options]
If source is a directory, this will create an archive from the contents of source. If source is a file, it should be an archive, and it will be copied to the target archive (or the contents of its shebang line will be displayed if the —info option is specified).
The following options are understood:
-o` `<output>``,` `--output``=<output>
Write the output to a file named output. If this option is not specified, the output filename will be the same as the input source, with the extension .pyz
added. If an explicit filename is given, it is used as is (so a .pyz
extension should be included if required).
An output filename must be specified if the source is an archive (and in that case, output must not be the same as source).
-p` `<interpreter>``,` `--python``=<interpreter>
Add a #!
line to the archive specifying interpreter as the command to run. Also, on POSIX, make the archive executable. The default is to write no #!
line, and not make the file executable.
-m` `<mainfn>``,` `--main``=<mainfn>
Write a __main__.py
file to the archive that executes mainfn. The mainfn argument should have the form “pkg.mod:fn”, where “pkg.mod” is a package/module in the archive, and “fn” is a callable in the given module. The __main__.py
file will execute that callable.
--main
cannot be specified when copying an archive.
-c``,` `--compress
Compress files with the deflate method, reducing the size of the output file. By default, files are stored uncompressed in the archive.
--compress
has no effect when copying an archive.
3.7 新版功能.
--info
Display the interpreter embedded in the archive, for diagnostic purposes. In this case, any other options are ignored and SOURCE must be an archive, not a directory.
-h``,` `--help
Print a short usage message and exit.
Python API
The module defines two convenience functions:
zipapp.create_archive
(source, target=None, interpreter=None, main=None, filter=None, compressed=False)
Create an application archive from source. The source can be any of the following:
- The name of a directory, or a path-like object referring to a directory, in which case a new application archive will be created from the content of that directory.
- The name of an existing application archive file, or a path-like object referring to such a file, in which case the file is copied to the target (modifying it to reflect the value given for the interpreter argument). The file name should include the
.pyz
extension, if required. - A file object open for reading in bytes mode. The content of the file should be an application archive, and the file object is assumed to be positioned at the start of the archive.
The target argument determines where the resulting archive will be written:
- If it is the name of a file, or a path-like object, the archive will be written to that file.
- If it is an open file object, the archive will be written to that file object, which must be open for writing in bytes mode.
- If the target is omitted (or
None
), the source must be a directory and the target will be a file with the same name as the source, with a.pyz
extension added.
The interpreter argument specifies the name of the Python interpreter with which the archive will be executed. It is written as a “shebang” line at the start of the archive. On POSIX, this will be interpreted by the OS, and on Windows it will be handled by the Python launcher. Omitting the interpreter results in no shebang line being written. If an interpreter is specified, and the target is a filename, the executable bit of the target file will be set.
The main argument specifies the name of a callable which will be used as the main program for the archive. It can only be specified if the source is a directory, and the source does not already contain a __main__.py
file. The main argument should take the form “pkg.module:callable” and the archive will be run by importing “pkg.module” and executing the given callable with no arguments. It is an error to omit main if the source is a directory and does not contain a __main__.py
file, as otherwise the resulting archive would not be executable.
The optional filter argument specifies a callback function that is passed a Path object representing the path to the file being added (relative to the source directory). It should return True
if the file is to be added.
The optional compressed argument determines whether files are compressed. If set to True
, files in the archive are compressed with the deflate method; otherwise, files are stored uncompressed. This argument has no effect when copying an existing archive.
If a file object is specified for source or target, it is the caller’s responsibility to close it after calling create_archive.
When copying an existing archive, file objects supplied only need read
and readline
, or write
methods. When creating an archive from a directory, if the target is a file object it will be passed to the zipfile.ZipFile
class, and must supply the methods needed by that class.
3.7 新版功能: Added the filter and compressed arguments.
zipapp.get_interpreter
(archive)
Return the interpreter specified in the #!
line at the start of the archive. If there is no #!
line, return None
. The archive argument can be a filename or a file-like object open for reading in bytes mode. It is assumed to be at the start of the archive.
例子
Pack up a directory into an archive, and run it.
$ python -m zipapp myapp
$ python myapp.pyz
<output from myapp>
The same can be done using the create_archive()
function:
>>> import zipapp
>>> zipapp.create_archive('myapp', 'myapp.pyz')
To make the application directly executable on POSIX, specify an interpreter to use.
$ python -m zipapp myapp -p "/usr/bin/env python"
$ ./myapp.pyz
<output from myapp>
To replace the shebang line on an existing archive, create a modified archive using the create_archive()
function:
>>> import zipapp
>>> zipapp.create_archive('old_archive.pyz', 'new_archive.pyz', '/usr/bin/python3')
To update the file in place, do the replacement in memory using a BytesIO
object, and then overwrite the source afterwards. Note that there is a risk when overwriting a file in place that an error will result in the loss of the original file. This code does not protect against such errors, but production code should do so. Also, this method will only work if the archive fits in memory:
>>> import zipapp
>>> import io
>>> temp = io.BytesIO()
>>> zipapp.create_archive('myapp.pyz', temp, '/usr/bin/python2')
>>> with open('myapp.pyz', 'wb') as f:
>>> f.write(temp.getvalue())
Specifying the Interpreter
Note that if you specify an interpreter and then distribute your application archive, you need to ensure that the interpreter used is portable. The Python launcher for Windows supports most common forms of POSIX #!
line, but there are other issues to consider:
- If you use “/usr/bin/env python” (or other forms of the “python” command, such as “/usr/bin/python”), you need to consider that your users may have either Python 2 or Python 3 as their default, and write your code to work under both versions.
- If you use an explicit version, for example “/usr/bin/env python3” your application will not work for users who do not have that version. (This may be what you want if you have not made your code Python 2 compatible).
- There is no way to say “python X.Y or later”, so be careful of using an exact version like “/usr/bin/env python3.4” as you will need to change your shebang line for users of Python 3.5, for example.
Typically, you should use an “/usr/bin/env python2” or “/usr/bin/env python3”, depending on whether your code is written for Python 2 or 3.
Creating Standalone Applications with zipapp
Using the zipapp
module, it is possible to create self-contained Python programs, which can be distributed to end users who only need to have a suitable version of Python installed on their system. The key to doing this is to bundle all of the application’s dependencies into the archive, along with the application code.
The steps to create a standalone archive are as follows:
Create your application in a directory as normal, so you have a
myapp
directory containing a__main__.py
file, and any supporting application code.Install all of your application’s dependencies into the
myapp
directory, using pip:$ python -m pip install -r requirements.txt --target myapp
(this assumes you have your project requirements in a
requirements.txt
file - if not, you can just list the dependencies manually on the pip command line).Optionally, delete the
.dist-info
directories created by pip in themyapp
directory. These hold metadata for pip to manage the packages, and as you won’t be making any further use of pip they aren’t required - although it won’t do any harm if you leave them.Package the application using:
$ python -m zipapp -p "interpreter" myapp
This will produce a standalone executable, which can be run on any machine with the appropriate interpreter available. See Specifying the Interpreter for details. It can be shipped to users as a single file.
On Unix, the myapp.pyz
file is executable as it stands. You can rename the file to remove the .pyz
extension if you prefer a “plain” command name. On Windows, the myapp.pyz[w]
file is executable by virtue of the fact that the Python interpreter registers the .pyz
and .pyzw
file extensions when installed.
Making a Windows executable
On Windows, registration of the .pyz
extension is optional, and furthermore, there are certain places that don’t recognise registered extensions “transparently” (the simplest example is that subprocess.run(['myapp'])
won’t find your application - you need to explicitly specify the extension).
On Windows, therefore, it is often preferable to create an executable from the zipapp. This is relatively easy, although it does require a C compiler. The basic approach relies on the fact that zipfiles can have arbitrary data prepended, and Windows exe files can have arbitrary data appended. So by creating a suitable launcher and tacking the .pyz
file onto the end of it, you end up with a single-file executable that runs your application.
A suitable launcher can be as simple as the following:
#define Py_LIMITED_API 1
#include "Python.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#ifdef WINDOWS
int WINAPI wWinMain(
HINSTANCE hInstance, /* handle to current instance */
HINSTANCE hPrevInstance, /* handle to previous instance */
LPWSTR lpCmdLine, /* pointer to command line */
int nCmdShow /* show state of window */
)
#else
int wmain()
#endif
{
wchar_t **myargv = _alloca((__argc + 1) * sizeof(wchar_t*));
myargv[0] = __wargv[0];
memcpy(myargv + 1, __wargv, __argc * sizeof(wchar_t *));
return Py_Main(__argc+1, myargv);
}
If you define the WINDOWS
preprocessor symbol, this will generate a GUI executable, and without it, a console executable.
To compile the executable, you can either just use the standard MSVC command line tools, or you can take advantage of the fact that distutils knows how to compile Python source:
>>> from distutils.ccompiler import new_compiler
>>> import distutils.sysconfig
>>> import sys
>>> import os
>>> from pathlib import Path
>>> def compile(src):
>>> src = Path(src)
>>> cc = new_compiler()
>>> exe = src.stem
>>> cc.add_include_dir(distutils.sysconfig.get_python_inc())
>>> cc.add_library_dir(os.path.join(sys.base_exec_prefix, 'libs'))
>>> # First the CLI executable
>>> objs = cc.compile([str(src)])
>>> cc.link_executable(objs, exe)
>>> # Now the GUI executable
>>> cc.define_macro('WINDOWS')
>>> objs = cc.compile([str(src)])
>>> cc.link_executable(objs, exe + 'w')
>>> if __name__ == "__main__":
>>> compile("zastub.c")
The resulting launcher uses the “Limited ABI”, so it will run unchanged with any version of Python 3.x. All it needs is for Python (python3.dll
) to be on the user’s PATH
.
For a fully standalone distribution, you can distribute the launcher with your application appended, bundled with the Python “embedded” distribution. This will run on any PC with the appropriate architecture (32 bit or 64 bit).
Caveats
There are some limitations to the process of bundling your application into a single file. In most, if not all, cases they can be addressed without needing major changes to your application.
- If your application depends on a package that includes a C extension, that package cannot be run from a zip file (this is an OS limitation, as executable code must be present in the filesystem for the OS loader to load it). In this case, you can exclude that dependency from the zipfile, and either require your users to have it installed, or ship it alongside your zipfile and add code to your
__main__.py
to include the directory containing the unzipped module insys.path
. In this case, you will need to make sure to ship appropriate binaries for your target architecture(s) (and potentially pick the correct version to add tosys.path
at runtime, based on the user’s machine). - If you are shipping a Windows executable as described above, you either need to ensure that your users have
python3.dll
on their PATH (which is not the default behaviour of the installer) or you should bundle your application with the embedded distribution. - The suggested launcher above uses the Python embedding API. This means that in your application,
sys.executable
will be your application, and not a conventional Python interpreter. Your code and its dependencies need to be prepared for this possibility. For example, if your application uses themultiprocessing
module, it will need to callmultiprocessing.set_executable()
to let the module know where to find the standard Python interpreter.
The Python Zip Application Archive Format
Python has been able to execute zip files which contain a __main__.py
file since version 2.6. In order to be executed by Python, an application archive simply has to be a standard zip file containing a __main__.py
file which will be run as the entry point for the application. As usual for any Python script, the parent of the script (in this case the zip file) will be placed on sys.path
and thus further modules can be imported from the zip file.
The zip file format allows arbitrary data to be prepended to a zip file. The zip application format uses this ability to prepend a standard POSIX “shebang” line to the file (#!/path/to/interpreter
).
Formally, the Python zip application format is therefore:
- An optional shebang line, containing the characters
b'#!'
followed by an interpreter name, and then a newline (b'\n'
) character. The interpreter name can be anything acceptable to the OS “shebang” processing, or the Python launcher on Windows. The interpreter should be encoded in UTF-8 on Windows, and insys.getfilesystemencoding()
on POSIX. - Standard zipfile data, as generated by the
zipfile
module. The zipfile content must include a file called__main__.py
(which must be in the “root” of the zipfile - i.e., it cannot be in a subdirectory). The zipfile data can be compressed or uncompressed.
If an application archive has a shebang line, it may have the executable bit set on POSIX systems, to allow it to be executed directly.
There is no requirement that the tools in this module are used to create application archives - the module is a convenience, but archives in the above format created by any means are acceptable to Python.
Python运行时服务
本章里描述的模块提供了和Python解释器及其环境交互相关的广泛服务。以下是综述:
sys
—- 系统相关的参数和函数sysconfig
—- Provide access to Python’s configuration information- 配置变量
- 安装路径
- 其他功能
- Using
sysconfig
as a script
builtins
—- 内建对象__main__
—- Top-level code environment__name__ == '__main__'
- What is the “top-level code environment”?
- Idiomatic Usage
- Packaging Considerations
__main__.py
in Python Packages- Idiomatic Usage
import __main__
warnings
—— 警告信息的控制- 警告类别
- 警告过滤器
- 警告过滤器的介绍
- 默认警告过滤器
- 重写默认的过滤器
- 暂时禁止警告
- 测试警告
- 为新版本的依赖关系更新代码
- 可用的函数
- 可用的上下文管理器
dataclasses
—- 数据类- 模块内容
- 初始化后处理
- 类变量
- 仅初始化变量
- 冻结的实例
- 继承
__init__()
中仅限关键字字段的重新排序- 默认工厂函数
- 可变的默认值
contextlib
—- 为with
语句上下文提供的工具- 工具
- 例子和配方
- Supporting a variable number of context managers
- Catching exceptions from
__enter__
methods - Cleaning up in an
__enter__
implementation - Replacing any use of
try-finally
and flag variables - Using a context manager as a function decorator
- Single use, reusable and reentrant context managers
- Reentrant context managers
- Reusable context managers
abc
—- 抽象基类atexit
—- 退出处理器atexit
示例
traceback
—- 打印或检索堆栈回溯TracebackException
ObjectsStackSummary
ObjectsFrameSummary
Objects- Traceback Examples
__future__
—- Future 语句定义gc
—- 垃圾回收器接口inspect
—- 检查对象- 类型和成员
- Retrieving source code
- Introspecting callables with the Signature object
- 类与函数
- The interpreter stack
- Fetching attributes statically
- Current State of Generators and Coroutines
- Code Objects Bit Flags
- 命令行界面
site
—— 指定域的配置钩子- Readline 配置
- 模块内容
- 命令行界面
sys
—- 系统相关的参数和函数
该模块提供了一些变量和函数。这些变量可能被解释器使用,也可能由解释器提供。这些函数会影响解释器。本模块总是可用的。
sys.abiflags
在POSIX系统上,以标准的 configure
脚本构建的 Python 中,这个变量会包含 PEP 3149 中定义的ABI标签。
在 3.8 版更改: 默认的 flags 变为了空字符串(用于 pymalloc 的 m
旗标已经移除)
3.2 新版功能.
sys.addaudithook
(hook)
将可调用对象 hook 附加到当前(子)解释器的活动的审计钩子列表中。
当通过 sys.audit()
函数引发审计事件时,每个钩子将按照其被加入的先后顺序被调用,调用时会传入事件名称和参数元组。 由 PySys_AddAuditHook()
添加的原生钩子会先被调用,然后是当前(子)解释器中添加的钩子。 接下来这些钩子会记录事件,引发异常来中止操作,或是完全终止进程。
调用 sys.addaudithook()
时它自身将引发一个名为 sys.addaudithook
的审计事件且不附带参数。 如果任何现有的钩子引发了派生自 RuntimeError
的异常,则新的钩子不会被添加并且该异常会被抑制。 其结果就是,调用者无法确保他们的钩子已经被添加,除非他们控制了全部现有的钩子。
3.8 新版功能.
在 3.8.1 版更改: 派生自 Exception
(而非 RuntimeError
)的异常不会被抑制。
CPython implementation detail: 启用跟踪时,仅当可调用对象(钩子)的 __cantrace__
成员设置为 true 时,才会跟踪该钩子。否则,跟踪功能将跳过该钩子。
sys.argv
一个列表,其中包含了被传递给 Python 脚本的命令行参数。 argv[0]
为脚本的名称(是否是完整的路径名取决于操作系统)。如果是通过 Python 解释器的命令行参数 -c
来执行的, argv[0]
会被设置成字符串 '-c'
。如果没有脚本名被传递给 Python 解释器, argv[0]
为空字符串。
注解
在 Unix 上,系统传递的命令行参数是字节类型的。Python 使用文件系统编码和 “surrogateescape” 错误处理方案对它们进行解码。当需要原始字节时,可以通过 [os.fsencode(arg) for arg in sys.argv]
来获取。
sys.audit
(event, \args*)
引发一个审计事件并触发任何激活的审计钩子。 event 是一个用于标识事件的字符串,args 会包含有关事件的更多信息的可选参数。 特定事件的参数的数量和类型会被视为是公有的稳定 API 且不应当在版本之间进行修改。
例如,有一个审计事件的名称为 os.chdir
。 此事件具有一个名为 path 的参数,该参数将包含所请求的新工作目录。
sys.audit()
将调用现有的审计钩子,传入事件名称和参数,并将重新引发来自任何钩子的第一个异常。 通常来说,如果有一个异常被引发,则它不应当被处理且其进程应当被尽可能快地终止。 这将允许钩子实现来决定对特定事件要如何反应:它们可以只是将事件写入日志或是通过引发异常来中止操作。
钩子程序由 sys.addaudithook()
或 PySys_AddAuditHook()
函数添加。
与本函数相等效的原生函数是 PySys_Audit()
,应尽量使用原生函数。
3.8 新版功能.
sys.base_exec_prefix
在 site.py
运行之前, Python 启动的时候被设置为跟 exec_prefix
同样的值。如果不是运行在 虚拟环境 中,两个值会保持相同;如果 site.py
发现处于一个虚拟环境中, prefix
和 exec_prefix
将会指向虚拟环境。然而 base_prefix
和 base_exec_prefix
将仍然会指向基础的 Python 环境(用来创建虚拟环境的 Python 环境)
3.3 新版功能.
sys.base_prefix
在 site.py
运行之前, Python 启动的时候被设置为跟 prefix
同样的值。如果不是运行在 虚拟环境 中, 两个值会保持相同;如果 site.py
发现处于一个虚拟环境中, prefix
和 exec_prefix
将会指向虚拟环境。然而 base_prefix
和 base_exec_prefix
将仍然会指向基础的 Python 环境(用来创建虚拟环境的 Python 环境)
3.3 新版功能.
sys.byteorder
本地字节顺序的指示符。在大端序(最高有效位优先)操作系统上值为 'big'
,在小端序(最低有效位优先)操作系统上为 'little'
。
sys.builtin_module_names
一个包含所有被编译进 Python 解释器的模块的名称的字符串元组。 (此信息无法通过任何其他办法获取 —- modules.keys()
仅会列出导入的模块。)
另请参阅 sys.stdlib_module_names
列表。
sys.call_tracing
(func, args)
在启用跟踪时调用 func(*args)
来保存跟踪状态,然后恢复跟踪状态。这将从检查点的调试器调用,以便递归地调试其他的一些代码。
sys.copyright
一个字符串,包含了 Python 解释器有关的版权信息
sys._clear_type_cache
()
清除内部的类型缓存。类型缓存是为了加速查找方法和属性的。在调试引用泄漏的时候调用这个函数 只会 清除不必要的引用。
这个函数应该只在内部为了一些特定的目的使用。
sys._current_frames
()
返回一个字典,存放着每个线程的标识符与(调用本函数时)该线程栈顶的帧(当前活动的帧)之间的映射。注意 traceback
模块中的函数可以在给定某一帧的情况下构建调用堆栈。
这对于调试死锁最有用:本函数不需要死锁线程的配合,并且只要这些线程的调用栈保持死锁,它们就是冻结的。在调用本代码来检查栈顶的帧的那一刻,非死锁线程返回的帧可能与该线程当前活动的帧没有任何关系。
这个函数应该只在内部为了一些特定的目的使用。
引发一个 审计事件 sys._current_frames
,没有附带参数。
sys._current_exceptions
()
返回一个字典,存放着每个线程的标识与调用此函数时该线程当前活动帧的栈顶异常之间的映射。 如果某个线程当前未在处理异常,它将不被包括在结果字典中。
这对于静态性能分析来说最为有用。
这个函数应该只在内部为了一些特定的目的使用。
引发一个 审计事件 sys._current_exceptions
,不附带任何参数。
sys.breakpointhook
()
本钩子函数由内建函数 breakpoint()
调用。默认情况下,它将进入 pdb
调试器,但可以将其改为任何其他函数,以选择使用哪个调试器。
该函数的特征取决于其调用的函数。例如,默认绑定(即 pdb.set_trace()
)不要求提供参数,但可以将绑定换成要求提供附加参数(位置参数/关键字参数)的函数。内建函数 breakpoint()
直接将其 *args
和 **kws
传入。breakpointhooks()
返回的所有内容都会从 breakpoint()
返回。
默认的实现首先会查询环境变量 PYTHONBREAKPOINT
。如果将该变量设置为 "0"
,则本函数立即返回,表示在断点处无操作。如果未设置该环境变量或将其设置为空字符串,则调用 pdb.set_trace()
。否则,此变量应指定要运行的函数,指定函数时应使用 Python 的点导入命名法,如 package.subpackage.module.function
。这种情况下将导入 package.subpackage.module
,且导入的模块必须有一个名为 function()
的可调用对象。该可调用对象会运行,*args
和 **kws
会传入,且无论 function()
返回什么,sys.breakpointhook()
都将返回到內建函数 breakpoint()
。
请注意,如果在导入 PYTHONBREAKPOINT
指定的可调用对象时出错,则将报告一个 RuntimeWarning
并忽略断点。
另请注意,如果以编程方式覆盖 sys.breakpointhook()
,则 不会 查询 PYTHONBREAKPOINT
。
3.7 新版功能.
sys._debugmallocstats
()
将有关 CPython 内存分配器状态的底层的信息打印至 stderr。
如果 Python 是 以调试模式编译的 <debug-build> (configure --with-pydebug option
),它还会执行一些消耗性能的内部一致性检查。
3.3 新版功能.
CPython implementation detail: 本函数仅限 CPython。此处没有定义确切的输出格式,且可能会更改。
sys.dllhandle
指向 Python DLL 句柄的整数。
可用性: Windows。
sys.displayhook
(value)
如果 value 不是 None
,则本函数会将 repr(value)
打印至 sys.stdout
,并将 value 保存在 builtins._
中。如果 repr(value)
无法用 sys.stdout.errors
错误处理方案(可能为 'strict'
)编码为 sys.stdout.encoding
,则用 'backslashreplace'
错误处理方案将其编码为 sys.stdout.encoding
。
在交互式 Python 会话中运行 expression 产生结果后,将在结果上调用 sys.displayhook
。若要自定义这些 value 的显示,可以将 sys.displayhook
指定为另一个单参数函数。
伪代码:
def displayhook(value):
if value is None:
return
# Set '_' to None to avoid recursion
builtins._ = None
text = repr(value)
try:
sys.stdout.write(text)
except UnicodeEncodeError:
bytes = text.encode(sys.stdout.encoding, 'backslashreplace')
if hasattr(sys.stdout, 'buffer'):
sys.stdout.buffer.write(bytes)
else:
text = bytes.decode(sys.stdout.encoding, 'strict')
sys.stdout.write(text)
sys.stdout.write("\n")
builtins._ = value
在 3.2 版更改: 在发生 UnicodeEncodeError
时使用 'backslashreplace'
错误处理方案。
sys.dont_write_bytecode
如果该值为 true,则 Python 在导入源码模块时将不会尝试写入 .pyc
文件。该值会被初始化为 True
或 False
,依据是 -B
命令行选项和 PYTHONDONTWRITEBYTECODE
环境变量,可以自行设置该值,来控制是否生成字节码文件。
sys.pycache_prefix
如果将该值设为某个目录(不是 None
),Python 会将字节码缓存文件 .pyc
写入到以该目录为根的并行目录树中(并从中读取),而不是在源码树中的 __pycache__
目录下读写。源码树中所有的 __pycache__
目录都将被忽略,并将在 pycache prefix 内写入新的 .pyc 文件。因此,如果使用 compileall
作为预构建步骤,则必须确保预构建时使用的 pycache prefix (如果有)与将来运行的时候相同。
相对路径将解释为相对于当前工作目录。
该值的初值设置,依据 -X
pycache_prefix=PATH
命令行选项或 PYTHONPYCACHEPREFIX
环境变量的值(命令行优先)。如果两者均未设置,则为 None
。
3.8 新版功能.
sys.excepthook
(type, value, traceback)
本函数会将所给的回溯和异常输出到 sys.stderr
中。
当抛出一个异常,且未被捕获时,解释器将调用 sys.excepthook
并带有三个参数:异常类、异常实例和一个回溯对象。在交互式会话中,这会在控制权返回到提示符之前发生。在 Python 程序中,这会在程序退出之前发生。如果要自定义此类顶级异常的处理过程,可以将另一个 3 个参数的函数赋给 sys.excepthook
。
引发一个 审计事件 sys.excepthook
,附带参数 hook
, type
, value
, traceback
。
参见
sys.unraisablehook()
函数处理无法抛出的异常,threading.excepthook()
函数处理 threading.Thread.run()
抛出的异常。
sys.__breakpointhook__
sys.__displayhook__
sys.__excepthook__
sys.__unraisablehook__
程序开始时,这些对象存有 breakpointhook
、displayhook
、excepthook
和 unraisablehook
的初始值。保存它们是为了可以在 breakpointhook
、displayhook
和 excepthook
、unraisablehook
被破坏或被替换时恢复它们。
3.7 新版功能: breakpointhook
3.8 新版功能: unraisablehook
sys.exc_info
()
本函数返回的元组包含三个值,它们给出当前正在处理的异常的信息。返回的信息仅限于当前线程和当前堆栈帧。如果当前堆栈帧没有正在处理的异常,则信息将从下级被调用的堆栈帧或上级调用者等位置获取,依此类推,直到找到正在处理异常的堆栈帧为止。此处的“处理异常”指的是“执行 except 子句”。任何堆栈帧都只能访问当前正在处理的异常的信息。
如果整个堆栈都没有正在处理的异常,则返回包含三个 None
值的元组。否则返回值为 (type, value, traceback)
。它们的含义是:type 是正在处理的异常类型(它是 BaseException
的子类);value 是异常实例(异常类型的实例);traceback 是一个 回溯对象,该对象封装了最初发生异常时的调用堆栈。
sys.exec_prefix
一个字符串,提供特定域的目录前缀,该目录中安装了与平台相关的 Python 文件,默认也是 '/usr/local'
。该目录前缀可以在构建时使用 configure 脚本的 --exec-prefix
参数进行设置。具体而言,所有配置文件(如 pyconfig.h
头文件)都安装在目录 *exec_prefix*/lib/python*X.Y*/config
中,共享库模块安装在 *exec_prefix*/lib/python*X.Y*/lib-dynload
中,其中 X.Y 是 Python 的版本号,如 3.2
。
注解
如果在一个 虚拟环境 中,那么该值将在 site.py
中被修改,指向虚拟环境。Python 安装位置仍然可以用 base_exec_prefix
来获取。
sys.executable
一个字符串,提供 Python 解释器的可执行二进制文件的绝对路径,仅在部分系统中此值有意义。如果 Python 无法获取其可执行文件的真实路径,则 sys.executable
将为空字符串或 None
。
sys.exit
([arg])
从 Python 中退出。实现方式是抛出一个 SystemExit
异常,因此异常抛出后 try
语句的 finally 分支的清除动作将被触发,这样可能会打断外层的退出尝试。
可选参数 arg 可以是表示退出状态的整数(默认为 0),也可以是其他类型的对象。如果它是整数,则 shell 等将 0 视为“成功终止”,非零值视为“异常终止”。大多数系统要求该值的范围是 0—127,否则会产生不确定的结果。某些系统为退出代码约定了特定的含义,但通常尚不完善;Unix 程序通常用 2 表示命令行语法错误,用 1 表示所有其他类型的错误。传入其他类型的对象,如果传入 None
等同于传入 0,如果传入其他对象则将其打印至 stderr
,且退出代码为 1。特别地,sys.exit("some error message")
可以在发生错误时快速退出程序。
由于 exit()
最终“只是”抛出一个异常,因此当从主线程调用时,只会从进程退出;而异常不会因此被打断。
在 3.6 版更改: 在 Python 解释器捕获 SystemExit
后,如果在清理中发生错误(如清除标准流中的缓冲数据时出错),则退出状态码将变为 120。
sys.flags
具名元组 flags 含有命令行标志的状态。这些属性是只读的。
attribute — 属性 | 标志 |
---|---|
debug |
-d |
inspect |
-i |
interactive |
-i |
isolated |
-I |
optimize |
-O 或 -OO |
dont_write_bytecode |
-B |
no_user_site |
-s |
no_site |
-S |
ignore_environment |
-E |
verbose |
-v |
bytes_warning |
-b |
quiet |
-q |
hash_randomization |
-R |
dev_mode |
-X dev (Python 开发模式) |
utf8_mode |
-X utf8 |
在 3.2 版更改: 为新的 -q
标志添加了 quiet
属性
3.2.3 新版功能: hash_randomization
属性
在 3.3 版更改: 删除了过时的 division_warning
属性
在 3.4 版更改: 为 -I
isolated
标志添加了 isolated
属性。
在 3.7 版更改: 为新的 Python 开发模式 添加了 dev_mode
属性,为新的 -X
utf8
标志添加了 utf8_mode
属性。
sys.float_info
一个 具名元组,存有浮点型的相关信息。它包含的是关于精度和内部表示的底层信息。这些值与标准头文件 float.h
中为 C 语言定义的各种浮点常量对应,详情请参阅 1999 ISO/IEC C 标准 [C99] 的 5.2.4.2.2 节,’Characteristics of floating types(浮点型的特性)’。
attribute — 属性 | float.h 宏 | 说明 |
---|---|---|
epsilon |
DBL_EPSILON | 大于 1.0 的最小值和 1.0 之间的差,表示为浮点数另请参阅 math.ulp() 。 |
dig |
DBL_DIG | 浮点数可以真实表示的最大十进制数字;见下文 |
mant_dig |
DBL_MANT_DIG | 浮点数精度:radix 基数下的浮点数有效位数 |
max |
DBL_MAX | 可表示的最大正浮点数(非无穷) |
max_exp |
DBL_MAX_EXP | 使得 radix**(e-1)** 是可表示的浮点数(非无穷)的最大整数 *e* |
max_10_exp |
DBL_MAX_10_EXP | 使得 10e 在可表示的浮点数(非无穷)范围内的最大整数 e |
min |
DBL_MIN | 可表示的最小正 规格化 浮点数使用 math.ulp(0.0) 获取可表示的最小正 非规格化 浮点数 |
min_exp |
DBL_MIN_EXP | 使得 radix**(e-1)** 是规格化浮点数的最小整数 *e* |
min_10_exp |
DBL_MIN_10_EXP | 使得 10e 是规格化浮点数的最小整数 e |
radix |
FLT_RADIX | 指数表示法中采用的基数 |
rounds |
FLT_ROUNDS | 整数常数,表示算术运算中的舍入方式。它反映了解释器启动时系统的 FLT_ROUNDS 宏的值。关于可能的值及其含义的说明,请参阅 C99 标准 5.2.4.2.2 节。 |
关于 sys.float_info.dig
属性的进一步说明。如果 s
是表示十进制数的字符串,而该数最多有 sys.float_info.dig
位有效数字,则将 s
转换为 float 再转回去将恢复原先相同十进制值的字符串:
>>> import sys
>>> sys.float_info.dig
15
>>> s = '3.14159265358979' # decimal string with 15 significant digits
>>> format(float(s), '.15g') # convert to float and back -> same value
'3.14159265358979'
但是对于超过 sys.float_info.dig
位有效数字的字符串,转换前后并非总是相同:
>>> s = '9876543211234567' # 16 significant digits is too many!
>>> format(float(s), '.16g') # conversion changes value
'9876543211234568'
一个字符串,反映 repr()
函数在浮点数上的行为。如果该字符串是 'short'
,那么对于(非无穷的)浮点数 x
,repr(x)
将会生成一个短字符串,满足 float(repr(x)) == x
的特性。这是 Python 3.1 及更高版本中的常见行为。否则 float_repr_style
的值将是 'legacy'
,此时 repr(x)
的行为方式将与 Python 3.1 之前的版本相同。
3.1 新版功能.
sys.getallocatedblocks
()
返回解释器当前已分配的内存块数,无论它们大小如何。本函数主要用于跟踪和调试内存泄漏。因为解释器有内部缓存,所以不同调用之间结果会变化。可能需要调用 _clear_type_cache()
和 gc.collect()
使结果更容易预测。
如果当前 Python 构建或实现无法合理地计算此信息,允许 getallocatedblocks()
返回 0。
3.4 新版功能.
sys.getandroidapilevel
()
返回一个整数,表示 Android 构建时 API 版本。
可用性:Android。
3.7 新版功能.
sys.getdefaultencoding
()
返回当前 Unicode 实现所使用的默认字符串编码名称。
sys.getdlopenflags
()
返回当前 dlopen()
调用所使用的标志位的值。标志值对应的符号名称可以在 os
模块中找到(形如 RTLD_xxx
的常量,如 os.RTLD_LAZY
)。
可用性: Unix。
sys.getfilesystemencoding
()
获取 文件系统编码格式: 与 文件系统错误处理句柄 一起使用以便在 Unicode 文件名和字节文件名之间进行转换。 文件系统错误处理句柄是由 getfilesystemencoding()
来返回的。
为获得最佳兼容性,在任何时候都应使用 str 来表示文件名,尽管使用 bytes 来表示文件名也是受支持的。 接受还返回文件名的函数应当支持 str 或 bytes 并在内部将其转换为系统首选的表示形式。
应使用 os.fsencode()
和 os.fsdecode()
来保证所采用的编码和错误处理方案都是正确的。
filesystem encoding and error handler 是在 Python 启动时通过 PyConfig_Read()
函数来配置的。
在 3.2 版更改: getfilesystemencoding()
的结果将不再有可能是 None
。
在 3.6 版更改: Windows 不再保证会返回 'mbcs'
。详情请参阅 PEP 529 和 _enablelegacywindowsfsencoding()
。
在 3.7 版更改: 返回 'utf-8'
,如果启用了 Python UTF-8 模式 的话。
sys.getfilesystemencodeerrors
()
获取 文件系统错误处理句柄: 该错误处理句柄与 文件系统编码格式 一起使用以便在 Unicode 文件名和字节文件名之间进程转换。 文件系统编码格式是由 getfilesystemencoding()
来返回的。
应使用 os.fsencode()
和 os.fsdecode()
来保证所采用的编码和错误处理方案都是正确的。
filesystem encoding and error handler 是在 Python 启动时通过 PyConfig_Read()
函数来配置的:
3.6 新版功能.
sys.getrefcount
(object)
返回 object 的引用计数。返回的计数通常比预期的多一,因为它包括了作为 getrefcount()
参数的这一次(临时)引用。
sys.getrecursionlimit
()
返回当前的递归限制值,即 Python 解释器堆栈的最大深度。此限制可防止无限递归导致的 C 堆栈溢出和 Python 崩溃。该值可以通过 setrecursionlimit()
设置。
sys.getsizeof
(object[, default])
返回对象的大小(以字节为单位)。该对象可以是任何类型。所有内建对象返回的结果都是正确的,但对于第三方扩展不一定正确,因为这与具体实现有关。
只计算直接分配给对象的内存消耗,不计算它所引用的对象的内存消耗。
对象不提供计算大小的方法时,如果传入过 default 则返回它,否则抛出 TypeError
异常。
如果对象由垃圾回收器管理,则 getsizeof()
将调用对象的 __sizeof__
方法,并在上层添加额外的垃圾回收器。
可以参考 recursive sizeof recipe 中的示例,关于递归调用 getsizeof()
来得到各个容器及其所有内容物的大小。
sys.getswitchinterval
()
返回解释器的“线程切换间隔时间”,请参阅 setswitchinterval()
。
3.2 新版功能.
sys._getframe
([depth])
返回来自调用栈的一个帧对象。如果传入可选整数 depth,则返回从栈顶往下相应调用层数的帧对象。如果该数比调用栈更深,则抛出 ValueError
。depth 的默认值是 0,返回调用栈顶部的帧。
引发一个 审计事件 sys._getframe
,没有附带参数。
CPython implementation detail: 这个函数应该只在内部为了一些特定的目的使用。不保证它在所有 Python 实现中都存在。
sys.getprofile
()
返回由 setprofile()
设置的性能分析函数。
sys.gettrace
()
返回由 settrace()
设置的跟踪函数。
CPython implementation detail: gettrace()
函数仅用于实现调试器,性能分析器,打包工具等。它的行为是实现平台的一部分,而不是语言定义的一部分,因此并非在所有 Python 实现中都可用。
sys.getwindowsversion
()
返回一个具名元组,描述当前正在运行的 Windows 版本。元素名称包括 major, minor, build, platform, service_pack, service_pack_minor, service_pack_major, suite_mask, product_type 和 platform_version。service_pack 包含一个字符串,platform_version 包含一个三元组,其他所有值都是整数。元素也可以通过名称来访问,所以 sys.getwindowsversion()[0]
与 sys.getwindowsversion().major
是等效的。为保持与旧版本的兼容性,只有前 5 个元素可以用索引检索。
platform 将会是 2 (VER_PLATFORM_WIN32_NT)
。
product_type 可能是以下值之一:
常量 | 含意 |
---|---|
1 (VER_NT_WORKSTATION) |
系统是工作站。 |
2 (VER_NT_DOMAIN_CONTROLLER) |
系统是域控制器。 |
3 (VER_NT_SERVER) |
系统是服务器,但不是域控制器。 |
本函数包装了 Win32 GetVersionEx()
函数,参阅 Microsoft 文档有关 OSVERSIONINFOEX()
的内容可获取这些字段的更多信息。
platform_version 返回当前操作系统的主要版本、次要版本和编译版本号,而不是为该进程所模拟的版本。 它旨在用于日志记录而非特性检测。
注解
platform_version 会从 kernel32.dll 获取版本号,这个版本可能与 OS 版本不同。 请使用 platform
模块来获取准确的 OS 版本号。
可用性: Windows。
在 3.2 版更改: 更改为具名元组,添加 service_pack_minor, service_pack_major, suite_mask 和 product_type。
在 3.6 版更改: 添加了 platform_version
sys.get_asyncgen_hooks
()
返回一个 asyncgen_hooks 对象,该对象类似于 namedtuple
,形式为 (firstiter, finalizer),其中 firstiter 和 finalizer 为 None
或函数,函数以 异步生成器迭代器 作为参数,并用于在事件循环中干预异步生成器的终结。
3.6 新版功能: 详情请参阅 PEP 525。
注解
本函数已添加至暂定软件包(详情请参阅 PEP 411 )。
sys.get_coroutine_origin_tracking_depth
()
获取由 set_coroutine_origin_tracking_depth()
设置的协程来源的追踪深度。
3.7 新版功能.
注解
本函数已添加至暂定软件包(详情请参阅 PEP 411 )。仅将其用于调试目的。
sys.hash_info
一个 具名元组,给出数字类型的哈希的实现参数。
attribute — 属性 | 说明 |
---|---|
width |
用于哈希值的位宽度 |
modulus |
用于数字散列方案的素数模数P。 |
inf |
为正无穷大返回的哈希值 |
nan |
(该属性已不再被使用) |
imag |
用于复数虚部的乘数 |
algorithm |
字符串、字节和内存视图的哈希算法的名称 |
hash_bits |
哈希算法的内部输出大小。 |
seed_bits |
散列算法的种子密钥的大小 |
3.2 新版功能.
在 3.4 版更改: 添加了 algorithm, hash_bits 和 seed_bits
sys.hexversion
编码为单个整数的版本号。该整数会确保每个版本都自增,其中适当包括了未发布版本。举例来说,要测试 Python 解释器的版本不低于 1.5.2,请使用:
if sys.hexversion >= 0x010502F0:
# use some advanced feature
...
else:
# use an alternative implementation or warn the user
...
之所以称它为 hexversion
,是因为只有将它传入内置函数 hex()
后,其结果才看起来有意义。也可以使用 具名元组 sys.version_info
,它对相同信息有着更人性化的编码。
关于 hexversion
的更多信息可以在 API 和 ABI 版本管理 中找到。
sys.implementation
一个对象,该对象包含当前运行的 Python 解释器的实现信息。所有 Python 实现中都必须存在下列属性。
name 是当前实现的标识符,如 'cpython'
。实际的字符串由 Python 实现定义,但保证是小写字母。
version 是一个具名元组,格式与 sys.version_info
相同。它表示 Python 实现 的版本。 另一个(由 sys.version_info
表示)是当前解释器遵循的相应 Python 语言 的版本,两者具有不同的含义。 例如,对于 PyPy 1.8,sys.implementation.version
可能是 sys.version_info(1, 8, 0, 'final', 0)
,而 sys.version_info
则是 sys.version_info(2, 7, 2, 'final', 0)
。对于 CPython 而言两个值是相同的,因为它是参考实现。
hexversion 是十六进制的实现版本,类似于 sys.hexversion
。
cache_tag 是导入机制使用的标记,用于已缓存模块的文件名。按照惯例,它将由实现的名称和版本组成,如 'cpython-33'
。但如果合适,Python 实现可以使用其他值。如果 cache_tag
被置为 None
,表示模块缓存已禁用。
sys.implementation
可能包含相应 Python 实现的其他属性。这些非标准属性必须以下划线开头,此处不详细阐述。无论其内容如何,sys.implementation
在解释器运行期间或不同实现版本之间都不会更改。(但是不同 Python 语言版本间可能会不同。)详情请参阅 PEP 421。
3.3 新版功能.
注解
新的必要属性的添加必须经过常规的 PEP 过程。详情请参阅 PEP 421。
sys.int_info
一个 具名元组,包含 Python 内部整数表示形式的信息。这些属性是只读的。
属性 | 说明 |
---|---|
bits_per_digit |
每个数字占有的位数。Python 内部将整数存储在基底 2**int_info.bits_per_digit |
sizeof_digit |
用于表示数字的C类型的字节大小 |
3.1 新版功能.
sys.__interactivehook__
当本属性存在,则以 交互模式 启动解释器时,将自动(不带参数地)调用本属性的值。该过程是在读取 PYTHONSTARTUP
文件之后完成的,所以可以在该文件中设置这一钩子。site
模块 设置了这一属性。
引发一个 审计事件 cpython.run_interactivehook
,附带参数 hook
。
3.4 新版功能.
sys.intern
(string)
将 string 插入 “interned” (驻留)字符串表,返回被插入的字符串 — 它是 string 本身或副本。驻留字符串对提高字典查找的性能很有用 — 如果字典中的键已驻留,且所查找的键也已驻留,则键(取散列后)的比较可以用指针代替字符串来比较。通常,Python 程序使用到的名称会被自动驻留,且用于保存模块、类或实例属性的字典的键也已驻留。
驻留字符串不是永久存在的,对 intern()
返回值的引用必须保留下来,才能发挥驻留字符串的优势。
sys.is_finalizing
()
如果 Python 解释器 正在关闭 则返回 True
,否则返回 False
。
3.5 新版功能.
sys.last_type
sys.last_value
sys.last_traceback
这三个变量并非总是有定义,仅当有异常未处理,且解释器打印了错误消息和堆栈回溯时,才会给它们赋值。它们的预期用途,是允许交互中的用户导入调试器模块,进行事后调试,而不必重新运行导致错误的命令。(通常使用 import pdb; pdb.pm()
进入事后调试器。)
这些变量的含义与上述 exc_info()
返回值的含义相同。
sys.maxsize
一个整数,表示 Py_ssize_t
类型的变量可以取到的最大值。在 32 位平台上通常为 2**31 - 1
,在 64 位平台上通常为 2**63 - 1
。
sys.maxunicode
一个整数,表示最大的 Unicode 码点值,如 1114111
(十六进制为 0x10FFFF
)。
在 3.3 版更改: 在 PEP 393 之前,sys.maxunicode
曾是 0xFFFF
或 0x10FFFF
,具体取决于配置选项,该选项指定将 Unicode 字符存储为 UCS-2 还是 UCS-4。
sys.meta_path
一个由 元路径查找器 对象组成的列表,当查找需要导入的模块时,会调用这些对象的 find_spec()
方法,观察这些对象是否能找到所需模块。调用 find_spec()
方法最少需要传入待导入模块的绝对名称。如果待导入模块包含在一个包中,则父包的 __path__
属性将作为第二个参数被传入。该方法返回 模块规格,找不到模块则返回 None
。
参见
importlib.abc.MetaPathFinder
抽象基类,定义了
meta_path
内的查找器对象的接口。importlib.machinery.+ModuleSpec
find_spec()
返回的实例所对应的具体类。
在 3.4 版更改: 在 Python 3.4 中通过 PEP 451 引入了 模块规格。早期版本的 Python 会寻找一个称为 find_module()
的方法。如果某个 meta_path
条目没有 find_spec()
方法,就会回退去调用前一种方法。
sys.modules
一个字典,将模块名称映射到已加载的模块。可以操作该字典来强制重新加载模块,或是实现其他技巧。但是,替换的字典不一定会按预期工作,并且从字典中删除必要的项目可能会导致 Python 崩溃。
sys.orig_argv
传给 Python 可执行文件的原始命令行参数列表。
3.10 新版功能.
sys.path
一个由字符串组成的列表,用于指定模块的搜索路径。初始化自环境变量 PYTHONPATH
,再加上一条与安装有关的默认路径。
程序启动时将初始化本列表,列表的第一项 path[0]
目录含有调用 Python 解释器的脚本。如果脚本目录不可用(比如以交互方式调用了解释器,或脚本是从标准输入中读取的),则 path[0]
为空字符串,这将导致 Python 优先搜索当前目录中的模块。注意,脚本目录将插入在 PYTHONPATH
的条目之前。
程序可以随意修改本列表用于自己的目的。只能向 sys.path
中添加 string 和 bytes 类型,其他数据类型将在导入期间被忽略。
参见
site
模块,该模块描述了如何使用 .pth 文件来扩展 sys.path
。
sys.path_hooks
一个由可调用对象组成的列表,这些对象接受一个路径作为参数,并尝试为该路径创建一个 查找器。如果成功创建查找器,则可调用对象将返回它,否则将引发 ImportError
异常。
本特性最早在 PEP 302 中被提及。
sys.path_importer_cache
一个字典,作为 查找器 对象的缓存。key 是传入 sys.path_hooks
的路径,value 是相应已找到的查找器。如果路径是有效的文件系统路径,但在 sys.path_hooks
中未找到查找器,则存入 None
。
本特性最早在 PEP 302 中被提及。
在 3.3 版更改: 未找到查找器时,改为存储 None
,而不是 imp.NullImporter
。
sys.platform
本字符串是一个平台标识符,举例而言,该标识符可用于将特定平台的组件追加到 sys.path
中。
对于 Unix 系统(除 Linux 和 AIX 外),该字符串是 Python 构建时的 uname -s
返回的小写操作系统名称,并附加了 uname -r
返回的系统版本的第一部分,如 'sunos5'
或 'freebsd8'
。除非需要检测特定版本的系统,否则建议使用以下习惯用法:
if sys.platform.startswith('freebsd'):
# FreeBSD-specific code here...
elif sys.platform.startswith('linux'):
# Linux-specific code here...
elif sys.platform.startswith('aix'):
# AIX-specific code here...
对于其他系统,值是:
系统 | 平台 值 |
---|---|
AIX | ‘aix’ |
Linux | ‘linux’ |
Windows | ‘win32’ |
Windows/Cygwin | ‘cygwin’ |
macOS | ‘darwin’ |
在 3.3 版更改: 在 Linux 上,sys.platform
将不再包含副版本号。它将总是 'linux'
而不是 'linux2'
或 'linux3'
。由于旧版本的 Python 会包含该版本号,因此推荐总是使用上述 startswith
习惯用法。
在 3.8 版更改: 在 AIX 上,sys.platform
将不再包含副版本号。它将总是 'aix'
而不是 'aix5'
或 'aix7'
。由于旧版本的 Python 会包含该版本号,因此推荐总是使用上述 startswith
习惯用法。
参见
os.name
更加简略。os.uname()
提供系统的版本信息。
platform
模块对系统的标识有更详细的检查。
sys.platlibdir
平台专用库目录。用于构建标准库的路径和已安装扩展模块的路径。
在大多数平台上,它等同于 "lib"
。在 Fedora 和 SuSE 上,它等同于给出了以下 sys.path
路径的 64 位平台上的 "lib64"
(其中 X.Y
是 Python 的 major.minor
版本)。
/usr/lib64/pythonX.Y/
:标准库(如os
模块的os.py
)/usr/lib64/pythonX.Y/lib-dynload/
:标准库的 C 扩展模块(如errno
模块,确切的文件名取决于平台)/usr/lib/pythonX.Y/site-packages/
(请使用lib
, 而非sys.platlibdir
): 第三方模块/usr/lib64/pythonX.Y/site-packages/
: 第三方包的 C 扩展模块
3.9 新版功能.
sys.prefix
一个字符串,给出特定域的目录前缀,该目录中安装了与平台不相关的 Python 文件,默认为 '/usr/local'
。该目录前缀可以在构建时使用 configure 脚本的 --prefix
参数进行设置。Python 库模块的的主要集合安装在目录 *prefix*/lib/python*X.Y*
,而与平台无关的头文件 (除了 pyconfig.h
) 保存在 *prefix*/include/python*X.Y*
, 其中 X.Y 是 Python 的版本号, 例如 3.2
.
注解
如果在一个 虚拟环境 中,那么该值将在 site.py
中被修改,指向虚拟环境。Python 安装位置仍然可以用 base_prefix
来获取。
sys.ps1
sys.ps2
字符串,指定解释器的首要和次要提示符。仅当解释器处于交互模式时,它们才有定义。这种情况下,它们的初值为 '>>> '
和 '... '
。如果赋给其中某个变量的是非字符串对象,则每次解释器准备读取新的交互式命令时,都会重新运行该对象的 str()
,这可以用来实现动态的提示符。
sys.setdlopenflags
(n)
设置解释器在调用 dlopen()
时用到的标志,例如解释器在加载扩展模块时。首先,调用 sys.setdlopenflags(0)
将在导入模块时对符号启用惰性解析。要在扩展模块之间共享符号,请调用 sys.setdlopenflags(os.RTLD_GLOBAL)
。标志值的符号名称可以在 os
模块中找到(即 RTLD_xxx
常量,如 os.RTLD_LAZY
)。
可用性: Unix。
sys.setprofile
(profilefunc)
设置系统的性能分析函数,该函数使得在 Python 中能够实现一个 Python 源代码性能分析器。性能分析函数的调用方式类似于系统的跟踪函数,但它是通过不同的事件调用的,例如,不是每执行一行代码就调用它一次(仅在调用某函数和从某函数返回时才会调用性能分析函数,但即使某函数发生异常也会算作返回事件)。该函数是特定于单个线程的,但是性能分析器无法得知线程之间的上下文切换,因此在存在多个线程的情况下使用它是没有意义的。另外,因为它的返回值不会被用到,所以可以简单地返回 None
。性能分析函数中的错误将导致其自身被解除设置。
性能分析函数应接收三个参数:frame、event 和 arg。frame 是当前的堆栈帧。event 是一个字符串:'call'
、'return'
、'c_call'
、'c_return'
或 'c_exception'
。arg 取决于事件类型。
引发一个 审计事件 sys.setprofile
,不附带任何参数。
这些事件具有以下含义:
'call'
表示调用了某个函数(或进入了其他的代码块)。性能分析函数将被调用,arg 为
None
。'return'
表示某个函数(或别的代码块)即将返回。性能分析函数将被调用,arg 是即将返回的值,如果此次返回事件是由于抛出异常,arg 为
None
。'c_call'
表示即将调用某个 C 函数。它可能是扩展函数或是内建函数。arg 是 C 函数对象。
'c_return'
表示返回了某个 C 函数。arg 是 C 函数对象。
'c_exception'
表示某个 C 函数抛出了异常。arg 是 C 函数对象。
sys.setrecursionlimit
(limit)
将 Python 解释器堆栈的最大深度设置为 limit。此限制可防止无限递归导致的 C 堆栈溢出和 Python 崩溃。
不同平台所允许的最高限值不同。当用户有需要深度递归的程序且平台支持更高的限值,可能就需要调高限值。进行该操作需要谨慎,因为过高的限值可能会导致崩溃。
如果新的限值低于当前的递归深度,将抛出 RecursionError
异常。
在 3.5.1 版更改: 如果新的限值低于当前的递归深度,现在将抛出 RecursionError
异常。
sys.setswitchinterval
(interval)
设置解释器的线程切换间隔时间(单位为秒)。该浮点数决定了“时间片”的理想持续时间,时间片将分配给同时运行的 Python 线程。请注意,实际值可能更高,尤其是使用了运行时间长的内部函数或方法时。同时,在时间间隔末尾调度哪个线程是操作系统的决定。解释器没有自己的调度程序。
3.2 新版功能.
sys.settrace
(tracefunc)
设置系统的跟踪函数,使得用户在 Python 中就可以实现 Python 源代码调试器。该函数是特定于单个线程的,所以要让调试器支持多线程,必须为正在调试的每个线程都用 settrace()
注册一个跟踪函数,或使用 threading.settrace()
。
跟踪函数应接收三个参数:frame、event 和 arg。frame 是当前的堆栈帧。event 是一个字符串:'call'
、'line'
、'return'
、'exception'
或 'opcode'
。arg 取决于事件类型。
每次进入 trace 函数的新的局部作用范围,都会调用 trace 函数( event 会被设置为 'call'
),它应该返回一个引用,指向即将用在新作用范围上的局部跟踪函数;如果不需要跟踪当前的作用范围,则返回 None
。
局部跟踪函数应返回对自身的引用(或对另一个函数的引用,用来在其作用范围内进行进一步的跟踪),或者返回 None
来停止跟踪其作用范围。
如果跟踪函数出错,则该跟踪函数将被取消设置,类似于调用 settrace(None)
。
这些事件具有以下含义:
'call'
表示调用了某个函数(或进入了其他的代码块)。全局跟踪函数将被调用,arg 为
None
。返回值将指定局部跟踪函数。'line'
表示解释器即将执行新一行代码或重新执行循环条件。局部跟踪函数将被调用,arg 为
None
,其返回值将指定新的局部跟踪函数。关于其工作原理的详细说明,请参见Objects/lnotab_notes.txt
。要在该堆栈帧禁用每行触发事件,可以在堆栈帧上将f_trace_lines
设置为False
。'return'
表示某个函数(或别的代码块)即将返回。局部跟踪函数将被调用,arg 是即将返回的值,如果此次返回事件是由于抛出异常,arg 为
None
。跟踪函数的返回值将被忽略。'exception'
表示发生了某个异常。局部跟踪函数将被调用,arg 是一个
(exception, value, traceback)
元组,返回值将指定新的局部跟踪函数。'opcode'
表示解释器即将执行一个新的操作码。局部跟踪函数将被调用,arg 为
None
,其返回值将指定新的局部跟踪函数。每操作码触发事件默认情况下都不发出:必须在堆栈帧上将f_trace_opcodes
显式地设置为True
来请求这些事件。
注意,由于异常是在链式调用中传播的,所以每一级都会产生一个 'exception'
事件。
更细微的用法是,可以显式地通过赋值 frame.f_trace = tracefunc
来设置跟踪函数,而不是用现有跟踪函数的返回值去间接设置它。当前帧上的跟踪函数必须激活,而 settrace()
还没有做这件事。注意,为了使上述设置起效,必须使用 settrace()
来安装全局跟踪函数才能启用运行时跟踪机制,但是它不必与上述是同一个跟踪函数(它可以是一个开销很低的跟踪函数,只返回 None
,即在各个帧上立即将其自身禁用)。
引发一个 审计事件 sys.settrace
,不附带任何参数。
CPython implementation detail: settrace()
函数仅用于实现调试器,性能分析器,打包工具等。它的行为是实现平台的一部分,而不是语言定义的一部分,因此并非在所有 Python 实现中都可用。
在 3.7 版更改: 添加了 'opcode'
事件类型;为帧对象添加了 f_trace_lines
和 f_trace_opcodes
属性
sys.set_asyncgen_hooks
(firstiter, finalizer)
接受两个可选的关键字参数,要求它们是可调用对象,且接受一个 异步生成器迭代器 作为参数。firstiter 对象将在异步生成器第一次迭代时调用。finalizer 将在异步生成器即将被销毁时调用。
引发一个 审计事件 sys.set_asyncgen_hooks_firstiter
,不附带任何参数。
引发一个 审计事件 sys.set_asyncgen_hooks_finalizer
,不附带任何参数。
之所以会引发两个审计事件,是因为底层的 API 由两个调用组成,每个调用都须要引发自己的事件。
3.6 新版功能: 更多详情请参阅 PEP 525,finalizer 方法的参考示例可参阅 Lib/asyncio/base_events.py 中 asyncio.Loop.shutdown_asyncgens
的实现。
注解
本函数已添加至暂定软件包(详情请参阅 PEP 411 )。
sys.set_coroutine_origin_tracking_depth
(depth)
用于启用或禁用协程溯源。启用后,协程对象上的 cr_origin
属性将包含一个元组,它由多个(文件名 filename,行号 line number,函数名 function name)元组组成,整个元组描述出了协程对象创建过程的回溯,元组首端是最近一次的调用。禁用后,cr_origin
将为 None。
要启用,请向 depth 传递一个大于零的值,它指定了有多少帧将被捕获信息。要禁用,请将 depth 置为零。
该设置是特定于单个线程的。
3.7 新版功能.
注解
本函数已添加至暂定软件包(详情请参阅 PEP 411 )。仅将其用于调试目的。
sys._enablelegacywindowsfsencoding
()
将 filesystem encoding and error handler 分别修改为 ‘mbcs’ 和 ‘replace’,以便与 3.6 之前版本的 Python 保持一致。
这等同于在启动 Python 前先定义好 PYTHONLEGACYWINDOWSFSENCODING
环境变量。
另请参阅 sys.getfilesystemencoding()
和 sys.getfilesystemencodeerrors()
。
可用性: Windows。
3.6 新版功能: 更多详情请参阅 PEP 529。
sys.stdin
sys.stdout
sys.stderr
解释器用于标准输入、标准输出和标准错误的 文件对象:
stdin
用于所有交互式输入(包括对input()
的调用);stdout
用于print()
和 expression 语句的输出,以及用于input()
的提示符;- 解释器自身的提示符和它的错误消息都发往
stderr
。
这些流都是常规 文本文件,与 open()
函数返回的对象一致。它们的参数选择如下:
编码格式和错误处理句柄是由
PyConfig.stdio_encoding
和PyConfig.stdio_errors
来初始化的。在 Windows 上,控制台设备使用 UTF-8。 非字符设备如磁盘文件和管道使用系统语言区域编码格式(例如 ANSI 代码页)。 非控制台字符设备如 NUL(例如当
isatty()
返回True
时)会在启动时分别让 stdin 和 stdout/stderr 使用控制台输入和输出代码页。 如果进程初始化时没有被附加到控制台则会使用默认的系统 locale encoding。要重写控制台的特殊行为,可以在启动 Python 前设置 PYTHONLEGACYWINDOWSSTDIO 环境变量。此时,控制台代码页将用于其他字符设备。
在所有平台上,都可以通过在 Python 启动前设置
PYTHONIOENCODING
环境变量来重写字符编码,或通过新的-X
utf8
命令行选项和PYTHONUTF8
环境变量来设置。但是,对 Windows 控制台来说,上述方法仅在设置了PYTHONLEGACYWINDOWSSTDIO
后才起效。交互模式下,
stdout
流是行缓冲的。其他情况下,它像常规文本文件一样是块缓冲的。两种情况下的stderr
流都是行缓冲的。要使得两个流都变成无缓冲,可以传入-u
命令行选项或设置PYTHONUNBUFFERED
环境变量。
在 3.9 版更改: 非交互模式下,stderr
现在是行缓冲的,而不是全缓冲的。
注解
要从标准流写入或读取二进制数据,请使用底层二进制 buffer
对象。例如,要将字节写入 stdout
,请使用 sys.stdout.buffer.write(b'abc')
。
但是,如果你在写一个库(并且不限制执行库代码时的上下文),那么请注意,标准流可能会被替换为文件类对象,如 io.StringIO
,它们是不支持 buffer
属性的。
sys.__stdin__
sys.__stdout__
sys.__stderr__
程序开始时,这些对象存有 stdin
、stderr
和 stdout
的初始值。它们在程序结束前都可以使用,且在需要向实际的标准流打印内容时很有用,无论 sys.std*
对象是否已重定向。
如果实际文件已经被覆盖成一个损坏的对象了,那它也可用于将实际文件还原成能正常工作的文件对象。但是,本过程的最佳方法应该是,在原来的流被替换之前就显式地保存它,并使用这一保存的对象来还原。
注解
某些情况下的 stdin
、stdout
和 stderr
以及初始值 __stdin__
、__stdout__
和 __stderr__
可以是 None
。通常发生在未连接到控制台的 Windows GUI app 中,以及在用 pythonw 启动的 Python app 中。
sys.stdlib_module_names
一个包含标准库模组名称字符串的冻结集合。
它在所有平台上都保持一致。 在某些平台上不可用的模块和在 Python 编译时被禁用的模块也会被列出。 所有种类的模块都会被列出:纯 Python 模块、内置模块、冻结模块和扩展模块等。 测试模块则会被排除掉。
对于包来说,仅会列出主包:子包和子模块不会被列出。 例如,email
包会被列出,但 email.mime
子包和 email.message
子模块不会被列出。
3.10 新版功能.
sys.thread_info
一个 具名元组,包含线程实现的信息。
属性 | 说明 |
---|---|
name |
线程实现的名称:‘nt’ : Windows 线程‘pthread’ : POSIX 线程‘solaris’ : Solaris 线程 |
lock |
锁实现的名称:‘semaphore’ : 锁使用信号量‘mutex+cond’ : 锁使用互斥和条件变量None 如果此信息未知 |
version |
线程库的名称和版本。它是一个字符串,如果此信息未知,则为 None 。 |
3.3 新版功能.
sys.tracebacklimit
当该变量值设置为整数,在发生未处理的异常时,它将决定打印的回溯信息的最大层级数。默认为 1000
。当将其设置为 0
或小于 0,将关闭所有回溯信息,并且只打印异常类型和异常值。
sys.unraisablehook
(unraisable, /)
处理一个无法抛出的异常。
它会在发生了一个异常但 Python 没有办法处理时被调用。例如,当一个析构器引发了异常,或在垃圾回收 (gc.collect()
) 期间引发了异常。
unraisable 参数具有以下属性:
- exc_type: 异常类型
- exc_value: 异常值,可以是
None
. - exc_traceback: 异常回溯,可以是
None
. - err_msg: 错误信息,可以是
None
. - object: 导致异常的对象,可以为
None
.
默认的钩子程序会将 err_msg 和 object 格式化为: f'{err_msg}: {object!r}'
;如果 err_msg 为 None
则采用 “Exception ignored in” 错误信息。
要改变无法抛出的异常的处理过程,可以重写 sys.unraisablehook()
。
使用定制钩子存放 exc_value 可能会创建引用循环。 它应当在不再需要异常时被显式地清空以打破引用循环。
如果一个 object 正在被销毁,那么使用自定义的钩子储存该对象可能会将其复活。请在自定义钩子生效后避免储存 object,以避免对象的复活。
另请参阅 excepthook()
,它处理未捕获的异常。
引发一个审计事件 sys.unraisablehook
并附带参数 hook
, unraisable
。
3.8 新版功能.
sys.version
一个包含 Python 解释器版本号加编译版本号以及所用编译器等额外信息的字符串。 此字符串会在交互式解释器启动时显示。 请不要从中提取版本信息,而应当使用 version_info
以及 platform
模块所提供的函数。
sys.api_version
这个解释器的 C API 版本。当你在调试 Python及期扩展模板的版本冲突这个功能非常有用。
sys.version_info
一个包含版本号五部分的元组: major, minor, micro, releaselevel 和 serial*。 除 *releaselevel 外的所有值均为整数;发布级别值则为 'alpha'
, 'beta'
, 'candidate'
或 'final'
。 对应于 Python 版本 2.0 的 version_info
值为 (2, 0, 0, 'final', 0)
。 这些部分也可按名称访问,因此 sys.version_info[0]
就等价于 sys.version_info.major
,依此类推。
在 3.1 版更改: 增加了以名称表示的各部分属性。
sys.warnoptions
这是警告框架的一个实现细节;请不要修改此值。 有关警告框架的更多信息请参阅 warnings
模块。
sys.winver
用于在 Windows 平台上组成注册表键的版本号。 这在 Python DLL 中存储为 1000 号字符串资源。 其值通常是 version
的头三个字符。 它在 sys
模块中提供是为了信息展示目的;修改此值不会影响 Python 所使用的注册表键。
可用性: Windows。
sys._xoptions
一个字典,包含通过 -X
命令行选项传递的旗标,这些旗标专属于各种具体实现。选项名称将会映射到对应的值(如果显式指定)或者 True
。例如:
$ ./python -Xa=b -Xc
Python 3.2a3+ (py3k, Oct 16 2010, 20:14:50)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys._xoptions
{'a': 'b', 'c': True}
CPython implementation detail: 这是 CPython 专属的访问通过 -X
传递的选项的方式。 其他实现可能会通过其他方式导出它们,或者完全不导出。
3.2 新版功能.
sysconfig
—- Provide access to Python’s configuration information
3.2 新版功能.
源代码: Lib/sysconfig.py
The sysconfig
module provides access to Python’s configuration information like the list of installation paths and the configuration variables relevant for the current platform.
配置变量
A Python distribution contains a Makefile
and a pyconfig.h
header file that are necessary to build both the Python binary itself and third-party C extensions compiled using distutils
.
sysconfig
puts all variables found in these files in a dictionary that can be accessed using get_config_vars()
or get_config_var()
.
Notice that on Windows, it’s a much smaller set.
sysconfig.get_config_vars
(\args*)
With no arguments, return a dictionary of all configuration variables relevant for the current platform.
With arguments, return a list of values that result from looking up each argument in the configuration variable dictionary.
For each argument, if the value is not found, return None
.
sysconfig.get_config_var
(name)
Return the value of a single variable name. Equivalent to get_config_vars().get(name)
.
If name is not found, return None
.
用法示例:
>>> import sysconfig
>>> sysconfig.get_config_var('Py_ENABLE_SHARED')
0
>>> sysconfig.get_config_var('LIBDIR')
'/usr/local/lib'
>>> sysconfig.get_config_vars('AR', 'CXX')
['ar', 'g++']
安装路径
Python uses an installation scheme that differs depending on the platform and on the installation options. These schemes are stored in sysconfig
under unique identifiers based on the value returned by os.name
.
Every new component that is installed using distutils
or a Distutils-based system will follow the same scheme to copy its file in the right places.
Python currently supports seven schemes:
- posix_prefix: scheme for POSIX platforms like Linux or macOS. This is the default scheme used when Python or a component is installed.
- posix_home: scheme for POSIX platforms used when a home option is used upon installation. This scheme is used when a component is installed through Distutils with a specific home prefix.
- posix_user: scheme for POSIX platforms used when a component is installed through Distutils and the user option is used. This scheme defines paths located under the user home directory.
- nt: scheme for NT platforms like Windows.
- nt_user: scheme for NT platforms, when the user option is used.
Each scheme is itself composed of a series of paths and each path has a unique identifier. Python currently uses eight paths:
- stdlib: directory containing the standard Python library files that are not platform-specific.
- platstdlib: directory containing the standard Python library files that are platform-specific.
- platlib: directory for site-specific, platform-specific files.
- purelib: directory for site-specific, non-platform-specific files.
- include: directory for non-platform-specific header files.
- platinclude: directory for platform-specific header files.
- scripts: directory for script files.
- data: directory for data files.
sysconfig
provides some functions to determine these paths.
sysconfig.get_scheme_names
()
Return a tuple containing all schemes currently supported in sysconfig
.
sysconfig.get_default_scheme
()
Return the default scheme name for the current platform.
在 3.10 版更改: This function was previously named _get_default_scheme()
and considered an implementation detail.
sysconfig.get_preferred_scheme
(key)
Return a preferred scheme name for an installation layout specified by key.
key must be either "prefix"
, "home"
, or "user"
.
The return value is a scheme name listed in get_scheme_names()
. It can be passed to sysconfig
functions that take a scheme argument, such as get_paths()
.
3.10 新版功能.
sysconfig._get_preferred_schemes
()
Return a dict containing preferred scheme names on the current platform. Python implementers and redistributors may add their preferred schemes to the _INSTALL_SCHEMES
module-level global value, and modify this function to return those scheme names, to e.g. provide different schemes for system and language package managers to use, so packages installed by either do not mix with those by the other.
End users should not use this function, but get_default_scheme()
and get_preferred_scheme()
instead.
3.10 新版功能.
sysconfig.get_path_names
()
Return a tuple containing all path names currently supported in sysconfig
.
sysconfig.get_path
(name[, scheme[, vars[, expand]]])
Return an installation path corresponding to the path name, from the install scheme named scheme.
name has to be a value from the list returned by get_path_names()
.
sysconfig
stores installation paths corresponding to each path name, for each platform, with variables to be expanded. For instance the stdlib path for the nt scheme is: {base}/Lib
.
get_path()
will use the variables returned by get_config_vars()
to expand the path. All variables have default values for each platform so one may call this function and get the default value.
If scheme is provided, it must be a value from the list returned by get_scheme_names()
. Otherwise, the default scheme for the current platform is used.
If vars is provided, it must be a dictionary of variables that will update the dictionary return by get_config_vars()
.
If expand is set to False
, the path will not be expanded using the variables.
If name is not found, raise a KeyError
.
sysconfig.get_paths
([scheme[, vars[, expand]]])
Return a dictionary containing all installation paths corresponding to an installation scheme. See get_path()
for more information.
If scheme is not provided, will use the default scheme for the current platform.
If vars is provided, it must be a dictionary of variables that will update the dictionary used to expand the paths.
If expand is set to false, the paths will not be expanded.
If scheme is not an existing scheme, get_paths()
will raise a KeyError
.
其他功能
sysconfig.get_python_version
()
Return the MAJOR.MINOR
Python version number as a string. Similar to '%d.%d' % sys.version_info[:2]
.
sysconfig.get_platform
()
Return a string that identifies the current platform.
This is used mainly to distinguish platform-specific build directories and platform-specific built distributions. Typically includes the OS name and version and the architecture (as supplied by ‘os.uname()’), although the exact information included depends on the OS; e.g., on Linux, the kernel version isn’t particularly important.
返回值的示例:
- linux-i586
- linux-alpha (?)
- solaris-2.6-sun4u
Windows将返回以下之一:
- win-amd64 (在 AMD64, aka x86_64, Intel64, 和 EM64T上的64位 Windows )
- win32 (all others - specifically, sys.platform is returned)
macOS can return:
- macosx-10.6-ppc
- macosx-10.4-ppc64
- macosx-10.3-i386
- macosx-10.4-fat
对于其他非-POSIX 平台, 目前只是返回 sys.platform
。
sysconfig.is_python_build
()
Return True
if the running Python interpreter was built from source and is being run from its built location, and not from a location resulting from e.g. running make install
or installing via a binary installer.
sysconfig.parse_config_h
(fp[, vars])
Parse a config.h
-style file.
fp is a file-like object pointing to the config.h
-like file.
A dictionary containing name/value pairs is returned. If an optional dictionary is passed in as the second argument, it is used instead of a new dictionary, and updated with the values read in the file.
sysconfig.get_config_h_filename
()
返回 pyconfig.h
的目录
sysconfig.get_makefile_filename
()
返回 Makefile
的目录
Using sysconfig
as a script
You can use sysconfig
as a script with Python’s -m option:
$ python -m sysconfig
Platform: "macosx-10.4-i386"
Python version: "3.2"
Current installation scheme: "posix_prefix"
Paths:
data = "/usr/local"
include = "/Users/tarek/Dev/svn.python.org/py3k/Include"
platinclude = "."
platlib = "/usr/local/lib/python3.2/site-packages"
platstdlib = "/usr/local/lib/python3.2"
purelib = "/usr/local/lib/python3.2/site-packages"
scripts = "/usr/local/bin"
stdlib = "/usr/local/lib/python3.2"
Variables:
AC_APPLE_UNIVERSAL_BUILD = "0"
AIX_GENUINE_CPLUSPLUS = "0"
AR = "ar"
ARFLAGS = "rc"
...
This call will print in the standard output the information returned by get_platform()
, get_python_version()
, get_path()
and get_config_vars()
.
builtins
—- 内建对象
该模块提供对Python的所有“内置”标识符的直接访问;例如,builtins.open
是内置函数的全名 open()
。
大多数应用程序通常不会显式访问此模块,但在提供与内置值同名的对象的模块中可能很有用,但其中还需要内置该名称。例如,在一个想要实现 open()
函数的模块中,它包装了内置的 open()
,这个模块可以直接使用:
import builtins
def open(path):
f = builtins.open(path, 'r')
return UpperCaser(f)
class UpperCaser:
'''Wrapper around a file that converts output to upper-case.'''
def __init__(self, f):
self._f = f
def read(self, count=-1):
return self._f.read(count).upper()
# ...
作为一个实现细节,大多数模块都将名称 __builtins__
作为其全局变量的一部分提供。 __builtins__
的值通常是这个模块或者这个模块的值 __dict__
属性。由于这是一个实现细节,因此 Python 的替代实现可能不会使用它。
__main__
—- Top-level code environment
In Python, the special name __main__
is used for two important constructs:
- the name of the top-level environment of the program, which can be checked using the
__name__ == '__main__'
expression; and - the
__main__.py
file in Python packages.
Both of these mechanisms are related to Python modules; how users interact with them and how they interact with each other. They are explained in detail below. If you’re new to Python modules, see the tutorial section 模块 for an introduction.
__name__ == '__main__'
When a Python module or package is imported, __name__
is set to the module’s name. Usually, this is the name of the Python file itself without the .py
extension:
>>> import configparser
>>> configparser.__name__
'configparser'
If the file is part of a package, __name__
will also include the parent package’s path:
>>> from concurrent.futures import process
>>> process.__name__
'concurrent.futures.process'
However, if the module is executed in the top-level code environment, its __name__
is set to the string '__main__'
.
What is the “top-level code environment”?
__main__
is the name of the environment where top-level code is run. “Top-level code” is the first user-specified Python module that starts running. It’s “top-level” because it imports all other modules that the program needs. Sometimes “top-level code” is called an entry point to the application.
The top-level code environment can be:
the scope of an interactive prompt:
>>> __name__ '__main__'
the Python module passed to the Python interpreter as a file argument:
$ python3 helloworld.py Hello, world!
the Python module or package passed to the Python interpreter with the
-m
argument:$ python3 -m tarfile usage: tarfile.py [-h] [-v] (...)
Python code read by the Python interpreter from standard input:
$ echo "import this" | python3 The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. ...
Python code passed to the Python interpreter with the
-c
argument:$ python3 -c "import this" The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. ...
In each of these situations, the top-level module’s __name__
is set to '__main__'
.
As a result, a module can discover whether or not it is running in the top-level environment by checking its own __name__
, which allows a common idiom for conditionally executing code when the module is not initialized from an import statement:
if __name__ == '__mainif __name__ == '__main__':
# Execute when the module is not initialized from an import statement.
...__': # Execute when the module is not initialized from an import statement. ...
参见
For a more detailed look at how __name__
is set in all situations, see the tutorial section 模块.
Idiomatic Usage
Some modules contain code that is intended for script use only, like parsing command-line arguments or fetching data from standard input. When a module like this were to be imported from a different module, for example to unit test it, the script code would unintentionally execute as well.
This is where using the if __name__ == '__main__'
code block comes in handy. Code within this block won’t run unless the module is executed in the top-level environment.
Putting as few statements as possible in the block below if __name___ == '__main__'
can improve code clarity and correctness. Most often, a function named main
encapsulates the program’s primary behavior:
# echo.py
import shlex
import sys
def echo(phrase: str) -> None:
"""A dummy wrapper around print."""
# for demonstration purposes, you can imagine that there is some
# valuable and reusable logic inside this function
print(phrase)
def main() -> int:
"""Echo the input arguments to standard output"""
phrase = shlex.join(sys.argv)
echo(phrase)
return 0
if __name__ == '__main__':
sys.exit(main()) # next section explains the use of sys.exit
Note that if the module didn’t encapsulate code inside the main
function but instead put it directly within the if __name__ == '__main__'
block, the phrase
variable would be global to the entire module. This is error-prone as other functions within the module could be unintentionally using the global variable instead of a local name. A main
function solves this problem.
Using a main
function has the added benefit of the echo
function itself being isolated and importable elsewhere. When echo.py
is imported, the echo
and main
functions will be defined, but neither of them will be called, because __name__ != '__main__'
.
Packaging Considerations
main
functions are often used to create command-line tools by specifying them as entry points for console scripts. When this is done, pip inserts the function call into a template script, where the return value of main
is passed into sys.exit()
. For example:
sys.exit(main())
Since the call to main
is wrapped in sys.exit()
, the expectation is that your function will return some value acceptable as an input to sys.exit()
; typically, an integer or None
(which is implicitly returned if your function does not have a return statement).
By proactively following this convention ourselves, our module will have the same behavior when run directly (i.e. python3 echo.py
) as it will have if we later package it as a console script entry-point in a pip-installable package.
In particular, be careful about returning strings from your main
function. sys.exit()
will interpret a string argument as a failure message, so your program will have an exit code of 1
, indicating failure, and the string will be written to sys.stderr
. The echo.py
example from earlier exemplifies using the sys.exit(main())
convention.
参见
Python Packaging User Guide contains a collection of tutorials and references on how to distribute and install Python packages with modern tools.
__main__.py
in Python Packages
If you are not familiar with Python packages, see section 包 of the tutorial. Most commonly, the __main__.py
file is used to provide a command-line interface for a package. Consider the following hypothetical package, “bandclass”:
bandclass
├── __init__.py
├── __main__.py
└── student.py
__main__.py
will be executed when the package itself is invoked directly from the command line using the -m
flag. For example:
$ python3 -m bandclass
This command will cause __main__.py
to run. How you utilize this mechanism will depend on the nature of the package you are writing, but in this hypothetical case, it might make sense to allow the teacher to search for students:
# bandclass/__main__.py
import sys
from .student import search_students
student_name = sys.argv[2] if len(sys.argv) >= 2 else ''
print(f'Found student: {search_students(student_name)}')
Note that from .student import search_students
is an example of a relative import. This import style must be used when referencing modules within a package. For more details, see 子包参考 in the 模块 section of the tutorial.
Idiomatic Usage
The contents of __main__.py
typically isn’t fenced with if __name__ == '__main__'
blocks. Instead, those files are kept short, functions to execute from other modules. Those other modules can then be easily unit-tested and are properly reusable.
If used, an if __name__ == '__main__'
block will still work as expected for a __main__.py
file within a package, because its __name__
attribute will include the package’s path if imported:
>>> import asyncio.__main__
>>> asyncio.__main__.__name__
'asyncio.__main__'
This won’t work for __main__.py
files in the root directory of a .zip file though. Hence, for consistency, minimal __main__.py
like the venv
one mentioned above are preferred.
参见
See venv
for an example of a package with a minimal __main__.py
in the standard library. It doesn’t contain a if __name__ == '__main__'
block. You can invoke it with python3 -m venv [directory]
.
See runpy
for more details on the -m
flag to the interpreter executable.
See zipapp
for how to run applications packaged as .zip files. In this case Python looks for a __main__.py
file in the root directory of the archive.
import __main__
Regardless of which module a Python program was started with, other modules running within that same program can import the top-level environment’s scope (namespace) by importing the __main__
module. This doesn’t import a __main__.py
file but rather whichever module that received the special name '__main__'
.
Here is an example module that consumes the __main__
namespace:
# namely.py
import __main__
def did_user_define_their_name():
return 'my_name' in dir(__main__)
def print_user_name():
if not did_user_define_their_name():
raise ValueError('Define the variable `my_name`!')
if '__file__' in dir(__main__):
print(__main__.my_name, "found in file", __main__.__file__)
else:
print(__main__.my_name)
Example usage of this module could be as follows:
# start.py
import sys
from namely import print_user_name
# my_name = "Dinsdale"
def main():
try:
print_user_name()
except ValueError as ve:
return str(ve)
if __name__ == "__main__":
sys.exit(main())
Now, if we started our program, the result would look like this:
$ python3 start.py
Define the variable `my_name`!
The exit code of the program would be 1, indicating an error. Uncommenting the line with my_name = "Dinsdale"
fixes the program and now it exits with status code 0, indicating success:
$ python3 start.py
Dinsdale found in file /path/to/start.py
Note that importing __main__
doesn’t cause any issues with unintentionally running top-level code meant for script use which is put in the if __name__ == "__main__"
block of the start
module. Why does this work?
Python inserts an empty __main__
module in sys.modules
at interpreter startup, and populates it by running top-level code. In our example this is the start
module which runs line by line and imports namely
. In turn, namely
imports __main__
(which is really start
). That’s an import cycle! Fortunately, since the partially populated __main__
module is present in sys.modules
, Python passes that to namely
. See Special considerations for main in the import system’s reference for details on how this works.
The Python REPL is another example of a “top-level environment”, so anything defined in the REPL becomes part of the __main__
scope:
>>> import namely
>>> namely.did_user_define_their_name()
False
>>> namely.print_user_name()
Traceback (most recent call last):
...
ValueError: Define the variable `my_name`!
>>> my_name = 'Jabberwocky'
>>> namely.did_user_define_their_name()
True
>>> namely.print_user_name()
Jabberwocky
Note that in this case the __main__
scope doesn’t contain a __file__
attribute as it’s interactive.
The __main__
scope is used in the implementation of pdb
and rlcompleter
.
warnings
—— 警告信息的控制
源代码: Lib/warnings.py
通常以下情况会引发警告:提醒用户注意程序中的某些情况,而这些情况(通常)还不值得触发异常并终止程序。例如,当程序用到了某个过时的模块时,就可能需要发出一条警告。
Python 程序员可调用本模块中定义的 warn()
函数来发布警告。(C 语言程序员则用 PyErr_WarnEx()
)。
警告信息通常会写入 sys.stderr
,但可以灵活改变,从忽略所有警告到变成异常都可以。警告的处理方式可以依据 警告类型 、警告信息的文本和发出警告的源位置而进行变化。同一源位置重复出现的警告通常会被抑制。
控制警告信息有两个阶段:首先,每次引发警告时,决定信息是否要发出;然后,如果要发出信息,就用可由用户设置的钩子进行格式化并打印输出。
警告过滤器 控制着是否发出警告信息,也即一系列的匹配规则和动作。调用 filterwarnings()
可将规则加入过滤器,调用 resetwarnings()
则可重置为默认状态。
警告信息的打印输出是通过调用 showwarning()
完成的,该函数可被重写;默认的实现代码是调用 formatwarning()
进行格式化,自己编写的代码也可以调用此格式化函数。
参见
利用 logging.captureWarnings()
可以采用标准的日志架构处理所有警告。
警告类别
警告的类别由一些内置的异常表示。这种分类有助于对警告信息进行分组过滤。
虽然在技术上警告类别属于 内置异常,但也只是在此记录一下而已,因为在概念上他们属于警告机制的一部分。
通过对某个标准的警告类别进行派生,用户代码可以定义其他的警告类别。 警告类别必须是 Warning
类的子类。
目前已定义了以下警告类别的类:
类 | 描述 |
---|---|
Warning |
这是所有警告类别的基类。它是 Exception 的子类。 |
UserWarning |
The default category for warn() . |
DeprecationWarning |
已废弃特性警告的基类,这些警告是为其他 Python 开发者准备的(默认会忽略,除非在 **main** 中用代码触发)。 |
SyntaxWarning |
用于警告可疑语法的基类。 |
RuntimeWarning |
用于警告可疑运行时特性的基类。 |
FutureWarning |
用于警告已废弃特性的基类,这些警告是为 Python 应用程序的最终用户准备的。 |
PendingDeprecationWarning |
用于警告即将废弃功能的基类(默认忽略)。 |
ImportWarning |
导入模块时触发的警告的基类(默认忽略)。 |
UnicodeWarning |
用于 Unicode 相关警告的基类。 |
BytesWarning |
bytes 和 bytearray 相关警告的基类。 |
ResourceWarning |
资源利用相关警告的基类。 |
在 3.7 版更改: 以前 DeprecationWarning
和 FutureWarning
是根据某个功能是否完全删除或改变其行为来区分的。现在是根据受众和默认警告过滤器的处理方式来区分的。
警告过滤器
警告过滤器控制着警告是否被忽略、显示或转为错误(触发异常)。
从概念上讲,警告过滤器维护着一个经过排序的过滤器类别列表;任何具体的警告都会依次与列表中的每种过滤器进行匹配,直到找到一个匹配项;过滤器决定了匹配项的处理方式。每个列表项均为 ( action , message , category , module , lineno ) 格式的元组,其中:
action 是以下字符串之一:
值 处置 “default”
为发出警告的每个位置(模块+行号)打印第一个匹配警告 “error”
将匹配警告转换为异常 “ignore”
从不打印匹配的警告 “always”
总是打印匹配的警告 “module”
为发出警告的每个模块打印第一次匹配警告(无论行号如何) “once”
无论位置如何,仅打印第一次出现的匹配警告 message 是包含正则表达式的字符串,警告信息的开头必须与之匹配。该表达式编译时不区分大小写。
category 是警告类别的类(
Warning
的子类),警告类别必须是其子类,才能匹配。module 是个字符串,包含了模块名称必须匹配的正则表达式。该表达式编译时大小写敏感。
lineno 是个整数,发生警告的行号必须与之匹配,或为
0
表示与所有行号匹配。
由于 Warning
类是由内置类 Exception
派生出来的,要把某个警告变成错误,只要触发category(message)
即可。
如果警告不匹配所有已注册的过滤器,那就会应用 “default” 动作(正如其名)。
警告过滤器的介绍
警告过滤器由传给 Python 解释器的命令行 -W
选项和 PYTHONWARNINGS
环境变量初始化。解释器在 sys.warningoptions
中保存了所有给出的参数,但不作解释;warnings
模块在第一次导入时会解析这些参数(无效的选项被忽略,并会先向 sys.stderr
打印一条信息)。
每个警告过滤器的设定格式为冒号分隔的字段序列:
action:message:category:module:line
这些字段的含义在 警告过滤器 中描述。当一行中列出多个过滤器时(如 PYTHONWARNINGS
),过滤器间用逗号隔开,后面的优先于前面的(因为是从左到右应用的,最近应用的过滤器优先于前面的)。
常用的警告过滤器适用于所有的警告、特定类别的警告、由特定模块和包引发的警告。下面是一些例子:
default # Show all warnings (even those ignored by default)
ignore # Ignore all warnings
error # Convert all warnings to errors
error::ResourceWarning # Treat ResourceWarning messages as errors
default::DeprecationWarning # Show DeprecationWarning messages
ignore,default:::mymodule # Only report warnings triggered by "mymodule"
error:::mymodule[.*] # Convert warnings to errors in "mymodule"
# and any subpackages of "mymodule"
默认警告过滤器
Python 默认安装了几个警告过滤器,可以通过 -W
命令行参数、 PYTHONWARNINGS
环境变量及调用 filterwarnings()
进行覆盖。
在常规发布的版本中,默认的警告过滤器包括(按优先顺序排列):
default::DeprecationWarning:__main__
ignore::DeprecationWarning
ignore::PendingDeprecationWarning
ignore::ImportWarning
ignore::ResourceWarning
在 调试版本 中,默认警告过滤器的列表是空的。
在 3.2 版更改: 除了 PendingDeprecationWarning
之外,DeprecationWarning
现在默认会被忽略。
在 3.7 版更改: DeprecationWarning
在被 __main__
中的代码直接触发时,默认会再次显示。
在 3.7 版更改: 如果指定两次 -b
,则 BytesWarning
不再出现在默认的过滤器列表中,而是通过 sys.warningoptions
进行配置。
重写默认的过滤器
Python 应用程序的开发人员可能希望在默认情况下向用户隐藏 所有 Python级别的警告,而只在运行测试或其他调试时显示这些警告。用于向解释器传递过滤器配置的 sys.warningoptions
属性可以作为一个标记,表示是否应该禁用警告:
import sys
if not sys.warnoptions:
import warnings
warnings.simplefilter("ignore")
建议 Python 代码测试的开发者使用如下代码,以确保被测代码默认显示 所有 警告:
import sys
if not sys.warnoptions:
import os, warnings
warnings.simplefilter("default") # Change the filter in this process
os.environ["PYTHONWARNINGS"] = "default" # Also affect subprocesses
最后,建议在 __main__
以外的命名空间运行用户代码的交互式开发者,请确保 DeprecationWarning
在默认情况下是可见的,可采用如下代码(这里 user_ns
是用于执行交互式输入代码的模块):
import warnings
warnings.filterwarnings("default", category=DeprecationWarning,
module=user_ns.get("__name__"))
暂时禁止警告
如果明知正在使用会引起警告的代码,比如某个废弃函数,但不想看到警告(即便警告已经通过命令行作了显式配置),那么可以使用 catch_warnings
上下文管理器来抑制警告。
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
fxn()
在上下文管理器中,所有的警告将被简单地忽略。这样就能使用已知的过时代码而又不必看到警告,同时也不会限制警告其他可能不知过时的代码。注意:只能保证在单线程应用程序中生效。如果两个以上的线程同时使用 catch_warnings
上下文管理器,行为不可预知。
测试警告
要测试由代码引发的警告,请采用 catch_warnings
上下文管理器。有了它,就可以临时改变警告过滤器以方便测试。例如,以下代码可捕获所有的警告以便查看:
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
# Trigger a warning.
fxn()
# Verify some things
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "deprecated" in str(w[-1].message)
也可以用 error
取代 always
,让所有的警告都成为异常。需要注意的是,如果某条警告已经因为 once
/ default
规则而被引发,那么无论设置什么过滤器,该条警告都不会再出现,除非该警告有关的注册数据被清除。
一旦上下文管理器退出,警告过滤器将恢复到刚进此上下文时的状态。这样在多次测试时可防止意外改变警告过滤器,从而导致不确定的测试结果。模块中的 showwarning()
函数也被恢复到初始值。注意:这只能在单线程应用程序中得到保证。如果两个以上的线程同时使用 catch_warnings
上下文管理器,行为未定义。
当测试多项操作会引发同类警告时,重点是要确保每次操作都会触发新的警告(比如,将警告设置为异常并检查操作是否触发异常,检查每次操作后警告列表的长度是否有增加,否则就在每次新操作前将以前的警告列表项删除)。
为新版本的依赖关系更新代码
在默认情况下,主要针对 Python 开发者(而不是 Python 应用程序的最终用户)的警告类别,会被忽略。
值得注意的是,这个“默认忽略”的列表包含 DeprecationWarning
(适用于每个模块,除了 __main__
),这意味着开发人员应该确保在测试代码时应将通常忽略的警告显示出来,以便未来破坏性 API 变化时及时收到通知(无论是在标准库还是第三方包)。
理想情况下,代码会有一个合适的测试套件,在运行测试时会隐含地启用所有警告(由 unittest
模块提供的测试运行程序就是如此)。
在不太理想的情况下,可以通过向 Python 解释器传入 -Wd
(这是 -W default
的简写) 或设置环境变量 PYTHONWARNINGS=default
来检查应用程序是否用到了已弃用的接口。 这样可以启用对所有警告的默认处理操作,包括那些默认忽略的警告。 要改变遇到警告后执行的动作,可以改变传给 -W
的参数 (例如 -W error
)。
可用的函数
warnings.warn
(message, category=None, stacklevel=1, source=None)
引发警告、忽略或者触发异常。 如果给出 category 参数,则必须是 警告类别类 ;默认为 UserWarning
。 或者 message 可为 Warning
的实例,这时 category 将被忽略,转而采用 message.__class__
。 在这种情况下,错误信息文本将是 str(message)
。 如果某条警告被 警告过滤器 改成了错误,本函数将触发一条异常。 参数 stacklevel 可供 Python 包装函数使用,比如:
def deprecation(message):
warnings.warn(message, DeprecationWarning, stacklevel=2)
这会让警告指向 deprecation()
的调用者,而不是 deprecation()
本身的来源(因为后者会破坏引发警告的目的)。
source 是发出 ResourceWarning
的被销毁对象。
在 3.6 版更改: 加入 source 参数。
warnings.warn_explicit
(message, category, filename, lineno, module=None, registry=None, module_globals=None, source=None)
这是 warn()
函数的底层接口,显式传入消息、类别、文件名和行号,以及可选的模块名和注册表(应为模块的 __warningregistry__
字典)。 模块名称默认为去除了 .py
的文件名;如果未传递注册表,警告就不会被抑制。 message 必须是个字符串,category 是 Warning
的子类;或者message 可为 Warning
的实例,且 category 将被忽略。
module_globals 应为发出警告的代码所用的全局命名空间。(该参数用于从 zip 文件或其他非文件系统导入模块时显式源码)。
source 是发出 ResourceWarning
的被销毁对象。
在 3.6 版更改: 加入 source 参数。
warnings.showwarning
(message, category, filename, lineno, file=None, line=None)
将警告信息写入文件。默认的实现代码是调用formatwarning(message, category, filename, lineno, line)
并将结果字符串写入 file ,默认文件为 sys.stderr
。通过将任何可调用对象赋给 warnings.showwarning
可替换掉该函数。line 是要包含在警告信息中的一行源代码;如果未提供 line,showwarning()
将尝试读取由filename 和 lineno 指定的行。
warnings.formatwarning
(message, category, filename, lineno, line=None)
以标准方式格式化一条警告信息。将返回一个字符串,可能包含内嵌的换行符,并以换行符结束。如果未提供 line*,formatwarning()
将尝试读取由 *filename 和 lineno 指定的行。
warnings.filterwarnings
(action, message=’’, category=Warning, module=’’, lineno=0, append=False)
在 警告过滤器种类 列表中插入一条数据项。默认情况下,该数据项将被插到前面;如果 append 为 True,则会插到后面。这里会检查参数的类型,编译 message 和 module 正则表达式,并将他们作为一个元组插入警告过滤器的列表中。如果两者都与某种警告匹配,那么靠近列表前面的数据项就会覆盖后面的项。省略的参数默认匹配任意值。
warnings.simplefilter
(action, category=Warning, lineno=0, append=False)
在 警告过滤器种类 列表中插入一条简单数据项。函数参数的含义与 filterwarnings()
相同,但不需要正则表达式,因为插入的过滤器总是匹配任何模块中的任何信息,只要类别和行号匹配即可。
warnings.resetwarnings
()
重置警告过滤器。这将丢弃之前对 filterwarnings()
的所有调用,包括 -W
命令行选项和对 simplefilter()
的调用效果。
可用的上下文管理器
class warnings.catch_warnings
(**, record=False, module=None*)
该上下文管理器会复制警告过滤器和 showwarning()
函数,并在退出时恢复。 如果 record 参数是 False
(默认),则在进入时会返回 None
。 如果 record 为 True
,则返回一个列表,列表由自定义 showwarning()
函数所用对象逐步填充(该函数还会抑制 sys.stdout
的输出)。 列表中每个对象的属性与 showwarning()
的参数名称相同。
module 参数代表一个模块,当导入 warnings
时,将被用于代替返回的模块,其过滤器将被保护。该参数主要是为了测试 warnings
模块自身。
注解
catch_warnings
管理器的工作方式,是替换并随后恢复模块的 showwarning()
函数和内部的过滤器种类列表。这意味着上下文管理器将会修改全局状态,因此不是线程安全的。
dataclasses
—- 数据类
这个模块提供了一个装饰器和一些函数,用于自动添加生成的 special method,例如 __init__()
和 __repr__()
到用户定义的类。 它最初描述于 PEP 557 。
在这些生成的方法中使用的成员变量是使用 PEP 526 类型标注来定义的。 例如以下代码:
from dataclasses import dataclass
@dataclass
class InventoryItem:
"""Class for keeping track of an item in inventory."""
name: str
unit_price: float
quantity_on_hand: int = 0
def total_cost(self) -> float:
return self.unit_price * self.quantity_on_hand
将在添加的内容中包括如下所示的 __init__()
:
def __init__(self, name: str, unit_price: float, quantity_on_hand: int = 0):
self.name = name
self.unit_price = unit_price
self.quantity_on_hand = quantity_on_hand
请注意,此方法会自动添加到类中:它不会在上面显示的 InventoryItem
定义中直接指定。
3.7 新版功能.
模块内容
@``dataclasses.dataclass
(**, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False*)
这个函数是 decorator ,用于将生成的 special method 添加到类中,如下所述。
dataclass()
装饰器会检查类以查找 field
。 field
被定义为具有 类型标注 的类变量。 除了下面描述的两个例外,在 dataclass()
中没有什么东西会去检查在变量标注中所指定的类型。
所有生成的方法中的字段顺序是它们在类定义中出现的顺序。
dataclass()
装饰器将向类中添加各种“dunder”方法,如下所述。 如果所添加的方法已存在于类中,则行为将取决于下面所列出的参数。 装饰器会返回调用它的类本身;不会创建新的类。
如果 dataclass()
仅用作没有参数的简单装饰器,它就像它具有此签名中记录的默认值一样。也就是说,这三种 dataclass()
用法是等价的:
@dataclass
class C:
...
@dataclass()
class C:
...
@dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False)
class C:
...
dataclass()
的参数有:
init
: 如果为真值(默认),将生成一个__init__()
方法。如果类已定义
__init__()
,则忽略此参数。repr
:如果为真值(默认),将生成一个__repr__()
方法。 生成的 repr 字符串将具有类名以及每个字段的名称和 repr ,按照它们在类中定义的顺序。不包括标记为从 repr 中排除的字段。 例如:InventoryItem(name='widget', unit_price=3.0, quantity_on_hand=10)
。如果类已定义
__repr__()
,则忽略此参数。eq
:如果为true(默认值),将生成__eq__()
方法。此方法将类作为其字段的元组按顺序比较。比较中的两个实例必须是相同的类型。如果类已定义
__eq__()
,则忽略此参数。order
:如果为真值(默认为False
),则__lt__()
、__le__()
、__gt__()
和__ge__()
方法将生成。 这将类作为其字段的元组按顺序比较。比较中的两个实例必须是相同的类型。如果order
为真值并且eq
为假值 ,则引发ValueError
。如果类已经定义了
__lt__()
、__le__()
、__gt__()
或者__ge__()
中的任意一个,将引发TypeError
。unsafe_hash
:如果为False
(默认值),则根据eq
和frozen
的设置方式生成__hash__()
方法。__hash__()
由内置的hash()
使用,当对象被添加到散列集合(如字典和集合)时。有一个__hash__()
意味着类的实例是不可变的。可变性是一个复杂的属性,取决于程序员的意图,__eq__()
的存在性和行为,以及dataclass()
装饰器中eq
和frozen
标志的值。默认情况下,
dataclass()
不会隐式添加__hash__()
方法,除非这样做是安全的。 它也不会添加或更改现有的明确定义的__hash__()
方法。 设置类属性__hash__ = None
对 Python 具有特定含义,如__hash__()
文档中所述。如果
__hash__()
没有显式定义,或者它被设为None
,则dataclass()
可能 会添加一个隐式__hash__()
方法。 虽然并不推荐,但你可以用unsafe_hash=True
来强制dataclass()
创建一个__hash__()
方法。 如果你的类在逻辑上不可变但却仍然可被修改那么可能就是这种情况。 这是一个特殊用例并且应当被仔细地考虑。以下是隐式创建
__hash__()
方法的规则。请注意,你不能在数据类中都使用显式的__hash__()
方法并设置unsafe_hash=True
;这将导致TypeError
。如果
eq
和frozen
都是 true,默认情况下dataclass()
将为你生成一个__hash__()
方法。如果eq
为 true 且frozen
为 false ,则__hash__()
将被设置为None
,标记它不可用(因为它是可变的)。如果eq
为 false ,则__hash__()
将保持不变,这意味着将使用超类的__hash__()
方法(如果超类是object
,这意味着它将回到基于id的hash)。frozen
: 如为真值 (默认值为False
),则对字段赋值将会产生异常。 这模拟了只读的冻结实例。 如果在类中定义了__setattr__()
或__delattr__()
则将会引发TypeError
。 参见下文的讨论。match_args
: 如果为真值 (默认值为True
),则将根据传给生成的__init__()
方法的形参列表来创建__match_args__
元组 (即使没有生成__init__()
也会创建,见上文)。 如果为假值,或者如果__match_args__
已在类中定义,则将不生成__match_args__
。
3.10 新版功能.
kw_only
: 如果为真值 (默认值为False
),则所有字段都将被标记为仅限关键字。 如果一个字段被标记为仅限关键字,则其唯一的影响是根据仅限关键字的字段生成的__init__()
形参必须使用调用__init__()
时传入的关键字来指定。 对于 dataclass 的任何其它方面都没有影响。
3.10 新版功能.
slots
: 如果为真值 (默认值为False
),则将生成__slots__
属性并将返回一个新类而非原来的类。 如果__slots__
已在类中定义,则会引发TypeError
。
3.10 新版功能.
field
s 可以选择使用普通的 Python 语法指定默认值:
@dataclass
class C:
a: int # 'a' has no default value
b: int = 0 # assign a default value for 'b'
在这个例子中, a
和 b
都将包含在添加的 __init__()
方法中,它们将被定义为:
def __init__(self, a: int, b: int = 0):
如果具有默认值的字段之后存在没有默认值的字段,将会引发 TypeError
。 无论此情况是发生在单个类中还是作为类继承的结果,都是如此。
dataclasses.field
(**, default=MISSING, default_factory=MISSING, init=True, repr=True, hash=None, compare=True, metadata=None, kw_only=MISSING*)
对于常见和简单的用例,不需要其他功能。但是,有些数据类功能需要额外的每字段信息。为了满足这种对附加信息的需求,你可以通过调用提供的 field()
函数来替换默认字段值。例如:
@dataclass
class C:
mylist: list[int] = field(default_factory=list)
c = C()
c.mylist += [1, 2, 3]
As shown above, the MISSING
value is a sentinel object used to detect if some parameters are provided by the user. This sentinel is used because None
is a valid value for some parameters with a distinct meaning. No code should directly use the MISSING
value.
field()
参数有:
default
:如果提供,这将是该字段的默认值。这是必需的,因为field()
调用本身会替换一般的默认值。default_factory
:如果提供,它必须是一个零参数可调用对象,当该字段需要一个默认值时,它将被调用。除了其他目的之外,这可以用于指定具有可变默认值的字段,如下所述。 同时指定default
和default_factory
将产生错误。init
:如果为true(默认值),则该字段作为参数包含在生成的__init__()
方法中。repr
:如果为true(默认值),则该字段包含在生成的__repr__()
方法返回的字符串中。hash
:这可以是布尔值或None
。如果为true,则此字段包含在生成的__hash__()
方法中。如果为None
(默认值),请使用compare
的值,这通常是预期的行为。如果字段用于比较,则应在 hash 中考虑该字段。不鼓励将此值设置为None
以外的任何值。设置
hash=False
但compare=True
的一个可能原因是,如果一个计算 hash 的代价很高的字段是检验等价性需要的,但还有其他字段可以计算类型的 hash 。 即使从 hash 中排除某个字段,它仍将用于比较。compare
:如果为true(默认值),则该字段包含在生成的相等性和比较方法中(__eq__()
,__gt__()
等等)。metadata
:这可以是映射或 None 。 None 被视为一个空的字典。这个值包含在MappingProxyType()
中,使其成为只读,并暴露在Field
对象上。数据类根本不使用它,它是作为第三方扩展机制提供的。多个第三方可以各自拥有自己的键值,以用作元数据中的命名空间。kw_only
: 如果为真值,则此字段将被标记为仅限关键字。 这将在当计算出所生成的__init__()
方法的形参时被使用。
3.10 新版功能.
如果通过调用 field()
指定字段的默认值,则该字段的类属性将替换为指定的 default
值。如果没有提供 default
,那么将删除类属性。目的是在 dataclass()
装饰器运行之后,类属性将包含字段的默认值,就像指定了默认值一样。例如,之后:
@dataclass
class C:
x: int
y: int = field(repr=False)
z: int = field(repr=False, default=10)
t: int = 20
类属性 C.z
将是 10
,类属性 C.t
将是 20
,类属性 C.x
和 C.y
将不设置。
class dataclasses.Field
Field
对象描述每个定义的字段。这些对象在内部创建,并由 fields()
模块级方法返回(见下文)。用户永远不应该直接实例化 Field
对象。 其有文档的属性是:
name
:字段的名字。type
:字段的类型。default
,default_factory
,init
,repr
,hash
,compare
,metadata
和kw_only
具有与field()
函数中对应参数相同的含义和值。
可能存在其他属性,但它们是私有的,不能被审查或依赖。
dataclasses.fields
(class_or_instance)
返回 Field
对象的元组,用于定义此数据类的字段。 接受数据类或数据类的实例。如果没有传递一个数据类或实例将引发 TypeError
。 不返回 ClassVar
或 InitVar
的伪字段。
dataclasses.asdict
(instance, **, dict_factory=dict*)
将数据类 instance
转换为字典(使用工厂函数 dict_factory
)。每个数据类都转换为其字段的字典,如 name: value
对。数据类、字典、列表和元组被递归。例如:
@dataclass
class Point:
x: int
y: int
@dataclass
class C:
mylist: list[Point]
p = Point(10, 20)
assert asdict(p) == {'x': 10, 'y': 20}
c = C([Point(0, 0), Point(10, 4)])
assert asdict(c) == {'mylist': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]}
引发 TypeError
如果 instance
不是数据类实例。
dataclasses.astuple
(instance, **, tuple_factory=tuple*)
将数据类 instance
转换为元组(通过使用工厂函数 tuple_factory
)。每个数据类都转换为其字段值的元组。数据类、字典、列表和元组被递归。
继续前一个例子:
assert astuple(p) == (10, 20)
assert astuple(c) == ([(0, 0), (10, 4)],)
引发 TypeError
如果 instance
不是数据类实例。
dataclasses.make_dataclass
(cls_name, fields, **, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False*)
新建一个名为 cls_name
的数据库,其字段在 fields
中定义,基类在 bases
中给出,并使用在 namespace
中给出的命名空间进行初始化。 fields
是一个可迭代对象,其中的每个元素均为 name
, (name, type)
或 (name, type, Field)
。 如果只提供了 name
,则 typing.Any
会被用作 type
。 init
, repr
, eq
, order
, unsafe_hash
, frozen
, match_args
, kw_only
和 slots
等值与它们在 dataclass()
中的含义相同。
此函数不是严格要求的,因为用于任何创建带有 __annotations__
的新类的 Python 机制都可以应用 dataclass()
函数将该类转换为数据类。提供此功能是为了方便。例如:
C = make_dataclass('C',
[('x', int),
'y',
('z', int, field(default=5))],
namespace={'add_one': lambda self: self.x + 1})
等价于
@dataclass
class C:
x: int
y: 'typing.Any'
z: int = 5
def add_one(self):
return self.x + 1
dataclasses.replace
(instance, /, **changes)
创建一个与 instance
的类型相同的新对象,用来自 changes
的值替换各个字段。 如果 instance
不是数据类,则会引发 TypeError
。 如果 changes
中的值没有指定字段,则会引发 TypeError
。
新返回的对象通过调用数据类的 __init__()
方法创建。这确保了如果存在 __post_init__()
,其也被调用。
如果存在没有默认值的仅初始化变量,必须在调用 replace()
时指定,以便它们可以传递给 __init__()
和 __post_init__()
。
changes
包含任何定义为 init=False
的字段是错误的。在这种情况下会引发 ValueError
。
提前提醒 init=False
字段在调用 replace()
时的工作方式。如果它们完全被初始化的话,它们不是从源对象复制的,而是在 __post_init__()
中初始化。估计 init=False
字段很少能被正确地使用。如果使用它们,那么使用备用类构造函数或者可能是处理实例复制的自定义 replace()
(或类似命名的)方法可能是明智的。
dataclasses.is_dataclass
(class_or_instance)
如果其形参为 dataclass 或其实例则返回 True
,否则返回 False
。
如果你需要知道一个类是否是一个数据类的实例(而不是一个数据类本身),那么再添加一个 not isinstance(obj, type)
检查:
def is_dataclass_instance(obj):
return is_dataclass(obj) and not isinstance(obj, type)
dataclasses.MISSING
一个表示缺失 default 或 default_factory 的监视值。
dataclasses.KW_ONLY
一个用作类型标注的监视值。 任何在伪字段之后的类型为 KW_ONLY
的字段会被标记为仅限关键字字段。 请注意在其他情况下 KW_ONLY
类型的伪字段会被完全忽略。 这包括此类字段的名称。 根据惯例,名称 _
会被用作 KW_ONLY
字段。 仅限关键字字段指明当类被实例化时 __init__()
形参必须以关键字形式来指定。
在这个例子中,字段 y
和 z
将被标记为仅限关键字字段:
@dataclass
class Point:
x: float
_: KW_ONLY
y: float
z: float
p = Point(0, y=1.5, z=2.0)
在单个数据类中,指定一个以上 KW_ONLY
类型的字段将导致错误。
exception dataclasses.FrozenInstanceError
在使用 frozen=True
定义的数据类上调用隐式定义的 __setattr__()
或 __delattr__()
时引发。 这是 AttributeError
的一个子类。
初始化后处理
生成的 __init__()
代码将调用一个名为 __post_init__()
的方法,如果在类上已经定义了 __post_init__()
。它通常被称为 self.__post_init__()
。但是,如果定义了任何 InitVar
字段,它们也将按照它们在类中定义的顺序传递给 __post_init__()
。 如果没有 __init__()
方法生成,那么 __post_init__()
将不会被自动调用。
在其他用途中,这允许初始化依赖于一个或多个其他字段的字段值。例如:
@dataclass
class C:
a: float
b: float
c: float = field(init=False)
def __post_init__(self):
self.c = self.a + self.b
由 dataclass()
所生成的 __init__()
方法不会调用基类的 __init__()
方法。 如果基类有需要被调用的 __init__()
方法,通常是在 __post_init__()
方法中调用此方法:
@dataclass
class Rectangle:
height: float
width: float
@dataclass
class Square(Rectangle):
side: float
def __post_init__(self):
super().__init__(self.side, self.side)
但是请注意,一般来说 dataclass 生成的 __init__()
方法不需要被调用,因为派生的 dataclass 将负责初始化任何自身为 dataclass 的基类的所有字段。
有关将参数传递给 __post_init__()
的方法,请参阅下面有关仅初始化变量的段落。
类变量
两个地方 dataclass()
实际检查字段类型的之一是确定字段是否是如 PEP 526 所定义的类变量。它通过检查字段的类型是否为 typing.ClassVar
来完成此操作。如果一个字段是一个 ClassVar
,它将被排除在考虑范围之外,并被数据类机制忽略。这样的 ClassVar
伪字段不会由模块级的 fields()
函数返回。
仅初始化变量
另一个 dataclass()
检查类型注解地方是为了确定一个字段是否是一个仅初始化变量。它通过查看字段的类型是否为 dataclasses.InitVar
类型来实现。如果一个字段是一个 InitVar
,它被认为是一个称为仅初始化字段的伪字段。因为它不是一个真正的字段,所以它不会被模块级的 fields()
函数返回。仅初始化字段作为参数添加到生成的 __init__()
方法中,并传递给可选的 __post_init__()
方法。数据类不会使用它们。
例如,假设一个字段将从数据库初始化,如果在创建类时未提供其值:
@dataclass
class C:
i: int
j: int = None
database: InitVar[DatabaseType] = None
def __post_init__(self, database):
if self.j is None and database is not None:
self.j = database.lookup('j')
c = C(10, database=my_database)
在这种情况下, fields()
将返回 i
和 j
的 Field
对象,但不包括 database
。
冻结的实例
无法创建真正不可变的 Python 对象。但是,通过将 frozen=True
传递给 dataclass()
装饰器,你可以模拟不变性。在这种情况下,数据类将向类添加 __setattr__()
和 __delattr__()
方法。 些方法在调用时会引发 FrozenInstanceError
。
使用 frozen=True
时会有很小的性能损失: __ init__()
不能使用简单的赋值来初始化字段,并必须使用 object.__setattr__()
。
继承
当数组由 dataclass()
装饰器创建时,它会查看反向 MRO 中的所有类的基类(即从 object
开始 ),并且对于它找到的每个数据类, 将该基类中的字段添加到字段的有序映射中。添加完所有基类字段后,它会将自己的字段添加到有序映射中。所有生成的方法都将使用这种组合的,计算的有序字段映射。由于字段是按插入顺序排列的,因此派生类会重载基类。一个例子:
@dataclass
class Base:
x: Any = 15.0
y: int = 0
@dataclass
class C(Base):
z: int = 10
x: int = 15
最后的字段列表依次是 x
、 y
、 z
。 x
的最终类型是 int
,如类 C
中所指定的那样。
为 C
生成的 __init__()
方法看起来像:
def __init__(self, x: int = 15, y: int = 0, z: int = 10):
__init__()
中仅限关键字字段的重新排序
在计算出 __init__()
所需要的形参之后,任何仅限关键字形参会被移至所有常规(非仅限关键字)形参的后面。 这是This is a requirement of how keyword-only parameters are implemented in Python 中实现仅限关键字形参所要求的:它们必须位于非仅限关键字形参之后。
在这个例子中,Base.y
, Base.w
, and D.t
是仅限关键字字段,而 Base.x
和 D.z
是常规字段:
@dataclass
class Base:
x: Any = 15.0
_: KW_ONLY
y: int = 0
w: int = 1
@dataclass
class D(Base):
z: int = 10
t: int = field(kw_only=True, default=0)
为 D
生成的 __init__()
方法看起来像是这样:
def __init__(self, x: Any = 15.0, z: int = 10, *, y: int = 0, w: int = 1, t: int = 0):
请注意形参原来在字段列表中出现的位置已被重新排序:前面是来自常规字段的形参而后面是来自仅限关键字字段的形参。
仅限关键字形参的相对顺序会在重新排序的 __init__()
形参列表中保持原样。
默认工厂函数
如果一个
field()
指定了一个default_factory
,当需要该字段的默认值时,将使用零参数调用它。例如,要创建列表的新实例,请使用:mylist: list = field(default_factory=list)
如果一个字段被排除在
__init__()
之外(使用init=False
)并且字段也指定default_factory
,则默认的工厂函数将始终从生成的__init__()
函数调用。发生这种情况是因为没有其他方法可以为字段提供初始值。
可变的默认值
Python 在类属性中存储默认成员变量值。思考这个例子,不使用数据类:
class C: x = [] def add(self, element): self.x.append(element) o1 = C() o2 = C() o1.add(1) o2.add(2) assert o1.x == [1, 2] assert o1.x is o2.x
请注意,类
C
的两个实例共享相同的类变量x
,如预期的那样。使用数据类, 如果 此代码有效:
@dataclass class D: x: List = [] def add(self, element): self.x += element
它生成的代码类似于:
class D: x = [] def __init__(self, x=x): self.x = x def add(self, element): self.x += element assert D().x is D().x
这与使用
C
类的原始示例具有相同的问题。 也就是说,当在创建类实例的时候D
类的两个实例没有为x
指定值则将共享同一个x
的副本。 因为数据类只是使用普通的 Python 类创建方式所以它们也会共享此行为。 数据类没有任何通用方式来检测这种情况。 相反地,dataclass()
装饰器在检测到类型为list
,dict
或set
的默认形参时将会引发TypeError
。 这是一个部分解决方案,但它确实能防止许多常见错误。使用默认工厂函数是一种创建可变类型新实例的方法,并将其作为字段的默认值:
@dataclass class D: x: list = field(default_factory=list) assert D().x is not D().x
contextlib
—- 为 with
语句上下文提供的工具
此模块为涉及 with
语句的常见任务提供了实用的工具。
工具
提供的函数和类:
class contextlib.AbstractContextManager
一个为实现了 object.__aenter__()
与 object.__aexit__()
的类提供的 abstract base class。 为 object.__aenter__()
提供的一个默认实现是返回 self
而 object.__aexit__()
是一个默认返回 None
的抽象方法。
3.6 新版功能.
class contextlib.AbstractAsyncContextManager
一个为实现了 object.__aenter__()
与 object.__aexit__()
的类提供的 abstract base class。 为 object.__aenter__()
提供的一个默认实现是返回 self
而 object.__aexit__()
是一个默认返回 None
的抽象方法。
3.7 新版功能.
@``contextlib.contextmanager
这个函数是一个 decorator ,它可以定义一个支持 with
语句上下文管理器的工厂函数, 而不需要创建一个类或区 __enter__()
与 __exit__()
方法。
尽管许多对象原生支持使用 with 语句,但有些需要被管理的资源并不是上下文管理器,并且没有实现 close()
方法而不能使用 contextlib.closing
。
下面是一个抽象的示例,展示如何确保正确的资源管理:
from contextlib import contextmanager
@contextmanager
def managed_resource(*args, **kwds):
# Code to acquire resource, e.g.:
resource = acquire_resource(*args, **kwds)
try:
yield resource
finally:
# Code to release resource, e.g.:
release_resource(resource)
>>> with managed_resource(timeout=3600) as resource:
... # Resource is released at the end of this block,
... # even if code in the block raises an exception
被装饰的函数在被调用时,必须返回一个 generator 迭代器。 这个迭代器必须只 yield 一个值出来,这个值会被用在 with
语句中,绑定到 as
后面的变量,如果给定了的话。
当生成器发生 yield 时,嵌套在 with
语句中的语句体会被执行。 语句体执行完毕离开之后,该生成器将被恢复执行。 如果在该语句体中发生了未处理的异常,则该异常会在生成器发生 yield 时重新被引发。 因此,你可以使用 try
…except
…finally
语句来捕获该异常(如果有的话),或确保进行了一些清理。 如果仅出于记录日志或执行某些操作(而非完全抑制异常)的目的捕获了异常,生成器必须重新引发该异常。 否则生成器的上下文管理器将向 with
语句指示该异常已经被处理,程序将立即在 with
语句之后恢复并继续执行。
contextmanager()
使用 ContextDecorator
因此它创建的上下文管理器不仅可以用在 with
语句中,还可以用作一个装饰器。当它用作一个装饰器时,每一次函数调用时都会隐式创建一个新的生成器实例(这使得 contextmanager()
创建的上下文管理器满足了支持多次调用以用作装饰器的需求,而非“一次性”的上下文管理器)。
在 3.2 版更改: ContextDecorator
的使用。
@``contextlib.asynccontextmanager
与
contextmanager()
类似,但创建的是 asynchronous context manager 。这个函数是一个 decorator ,它可以定义一个支持
async with
语句的异步上下文管理器的工厂函数, 而不需要创建一个类或区分__aenter__()
与__aexit__()
方法。它必须被作用在一个 asynchronous generator 函数上一个简单的示例:
from contextlib import asynccontextmanager @asynccontextmanager async def get_connection(): conn = await acquire_db_connection() try: yield conn finally: await release_db_connection(conn) async def get_all_users(): async with get_connection() as conn: return conn.query('SELECT ...')
3.7 新版功能.
Context managers defined with
asynccontextmanager()
can be used either as decorators or withasync with
statements:import time async def timeit(): now = time.monotonic() try: yield finally: print(f'it took {time.monotonic() - now}s to run') @timeit() async def main(): # ... async code ...
When used as a decorator, a new generator instance is implicitly created on each function call. This allows the otherwise “one-shot” context managers created by
asynccontextmanager()
to meet the requirement that context managers support multiple invocations in order to be used as decorators.
在 3.10 版更改: Async context managers created with asynccontextmanager()
can be used as decorators.
contextlib.closing
(thing)
返回一个在语句块执行完成时关闭 things 的上下文管理器。这基本上等价于:
from contextlib import contextmanager
@contextmanager
def closing(thing):
try:
yield thing
finally:
thing.close()
并允许你编写这样的代码:
from contextlib import closing
from urllib.request import urlopen
with closing(urlopen('https://www.python.org')) as page:
for line in page:
print(line)
而无需显式地关闭 page
。 即使发生错误,在退出 with
语句块时, page.close()
也同样会被调用。
class contextlib.aclosing
(thing)
Return an async context manager that calls the aclose()
method of thing upon completion of the block. This is basically equivalent to:
from contextlib import asynccontextmanager
@asynccontextmanager
async def aclosing(thing):
try:
yield thing
finally:
await thing.aclose()
Significantly, aclosing()
supports deterministic cleanup of async generators when they happen to exit early by break
or an exception. For example:
from contextlib import aclosing
async with aclosing(my_generator()) as values:
async for value in values:
if value == 42:
break
This pattern ensures that the generator’s async exit code is executed in the same context as its iterations (so that exceptions and context variables work as expected, and the exit code isn’t run after the lifetime of some task it depends on).
3.10 新版功能.
contextlib.nullcontext
(enter_result=None)
返回一个从 __enter__
返回 enter_result 的上下文管理器,除此之外不执行任何操作。它旨在用于可选上下文管理器的一种替代,例如:
def myfunction(arg, ignore_exceptions=False):
if ignore_exceptions:
# Use suppress to ignore all exceptions.
cm = contextlib.suppress(Exception)
else:
# Do not ignore any exceptions, cm has no effect.
cm = contextlib.nullcontext()
with cm:
# Do something
一个使用 enter_result 的例子:
def process_file(file_or_path):
if isinstance(file_or_path, str):
# If string, open file
cm = open(file_or_path)
else:
# Caller is responsible for closing file
cm = nullcontext(file_or_path)
with cm as file:
# Perform processing on the file
It can also be used as a stand-in for asynchronous context managers:
async def send_http(session=None):
if not session:
# If no http session, create it with aiohttp
cm = aiohttp.ClientSession()
else:
# Caller is responsible for closing the session
cm = nullcontext(session)
async with cm as session:
# Send http requests with session
3.7 新版功能.
在 3.10 版更改: asynchronous context manager support was added.
contextlib.suppress
(\exceptions*)
Return a context manager that suppresses any of the specified exceptions if they occur in the body of a with
statement and then resumes execution with the first statement following the end of the with
statement.
与完全抑制异常的任何其他机制一样,该上下文管理器应当只用来抑制非常具体的错误,并确保该场景下静默地继续执行程序是通用的正确做法。
例如:
from contextlib import suppress
with suppress(FileNotFoundError):
os.remove('somefile.tmp')
with suppress(FileNotFoundError):
os.remove('someotherfile.tmp')
这段代码等价于:
try:
os.remove('somefile.tmp')
except FileNotFoundError:
pass
try:
os.remove('someotherfile.tmp')
except FileNotFoundError:
pass
该上下文管理器是 reentrant 。
3.4 新版功能.
contextlib.redirect_stdout
(new_target)
用于将 sys.stdout
临时重定向到一个文件或类文件对象的上下文管理器。
该工具给已有的将输出硬编码写到 stdout 的函数或类提供了额外的灵活性。
For example, the output of help()
normally is sent to sys.stdout. You can capture that output in a string by redirecting the output to an io.StringIO
object. The replacement stream is returned from the __enter__
method and so is available as the target of the with
statement:
with redirect_stdout(io.StringIO()) as f:
help(pow)
s = f.getvalue()
如果要把 help()
的输出写到磁盘上的一个文件,重定向该输出到一个常规文件:
with open('help.txt', 'w') as f:
with redirect_stdout(f):
help(pow)
如果要把 help()
的输出写到 sys.stderr :
with redirect_stdout(sys.stderr):
help(pow)
需要注意的点在于, sys.stdout
的全局副作用意味着此上下文管理器不适合在库代码和大多数多线程应用程序中使用。它对子进程的输出没有影响。不过对于许多工具脚本而言,它仍然是一个有用的方法。
该上下文管理器是 reentrant 。
3.4 新版功能.
contextlib.redirect_stderr
(new_target)
与 redirect_stdout()
类似,不过是将 sys.stderr
重定向到一个文件或类文件对象。
该上下文管理器是 reentrant 。
3.5 新版功能.
class contextlib.ContextDecorator
一个使上下文管理器能用作装饰器的基类。
与往常一样,继承自 ContextDecorator
的上下文管理器必须实现 __enter__
与 __exit__
。即使用作装饰器, __exit__
依旧会保持可能的异常处理。
ContextDecorator
被用在 contextmanager()
中,因此你自然获得了这项功能。
ContextDecorator
的示例:
from contextlib import ContextDecorator
class mycontext(ContextDecorator):
def __enter__(self):
print('Starting')
return self
def __exit__(self, *exc):
print('Finishing')
return False
>>> @mycontext()
... def function():
... print('The bit in the middle')
...
>>> function()
Starting
The bit in the middle
Finishing
>>> with mycontext():
... print('The bit in the middle')
...
Starting
The bit in the middle
Finishing
这个改动只是针对如下形式的一个语法糖:
def f():
with cm():
# Do stuff
ContextDecorator
使得你可以这样改写:
@cm()
def f():
# Do stuff
这能清楚地表明, cm
作用于整个函数,而不仅仅是函数的一部分(同时也能保持不错的缩进层级)。
现有的上下文管理器即使已经有基类,也可以使用 ContextDecorator
作为混合类进行扩展:
from contextlib import ContextDecorator
class mycontext(ContextBaseClass, ContextDecorator):
def __enter__(self):
return self
def __exit__(self, *exc):
return False
注解
由于被装饰的函数必须能够被多次调用,因此对应的上下文管理器必须支持在多个 with
语句中使用。如果不是这样,则应当使用原来的具有显式 with
语句的形式使用该上下文管理器。
3.2 新版功能.
class contextlib.AsyncContextDecorator
Similar to ContextDecorator
but only for asynchronous functions.
Example of AsyncContextDecorator
:
from asyncio import run
from contextlib import AsyncContextDecorator
class mycontext(AsyncContextDecorator):
async def __aenter__(self):
print('Starting')
return self
async def __aexit__(self, *exc):
print('Finishing')
return False
>>> @mycontext()
... async def function():
... print('The bit in the middle')
...
>>> run(function())
Starting
The bit in the middle
Finishing
>>> async def function():
... async with mycontext():
... print('The bit in the middle')
...
>>> run(function())
Starting
The bit in the middle
Finishing
3.10 新版功能.
class contextlib.ExitStack
该上下文管理器的设计目标是使得在编码中组合其他上下文管理器和清理函数更加容易,尤其是那些可选的或由输入数据驱动的上下文管理器。
例如,通过一个如下的 with 语句可以很容易处理一组文件:
with ExitStack() as stack:
files = [stack.enter_context(open(fname)) for fname in filenames]
# All opened files will automatically be closed at the end of
# the with statement, even if attempts to open files later
# in the list raise an exception
每个实例维护一个注册了一组回调的栈,这些回调在实例关闭时以相反的顺序被调用(显式或隐式地在 with
语句的末尾)。请注意,当一个栈实例被垃圾回收时,这些回调将 不会 被隐式调用。
通过使用这个基于栈的模型,那些通过 __init__
方法获取资源的上下文管理器(如文件对象)能够被正确处理。
由于注册的回调函数是按照与注册相反的顺序调用的,因此最终的行为就像多个嵌套的 with
语句用在这些注册的回调函数上。这个行为甚至扩展到了异常处理:如果内部的回调函数抑制或替换了异常,则外部回调收到的参数是基于该更新后的状态得到的。
这是一个相对底层的 API,它负责正确处理栈里回调退出时依次展开的细节。它为相对高层的上下文管理器提供了一个合适的基础,使得它能根据应用程序的需求使用特定方式操作栈。
3.3 新版功能.
enter_context
(cm)Enters a new context manager and adds its
__exit__()
method to the callback stack. The return value is the result of the context manager’s own__enter__()
method.These context managers may suppress exceptions just as they normally would if used directly as part of a
with
statement.push
(exit)Adds a context manager’s
__exit__()
method to the callback stack.As
__enter__
is not invoked, this method can be used to cover part of an__enter__()
implementation with a context manager’s own__exit__()
method.If passed an object that is not a context manager, this method assumes it is a callback with the same signature as a context manager’s
__exit__()
method and adds it directly to the callback stack.By returning true values, these callbacks can suppress exceptions the same way context manager
__exit__()
methods can.The passed in object is returned from the function, allowing this method to be used as a function decorator.
callback
(callback, /, \args, *kwds)Accepts an arbitrary callback function and arguments and adds it to the callback stack.
Unlike the other methods, callbacks added this way cannot suppress exceptions (as they are never passed the exception details).
The passed in callback is returned from the function, allowing this method to be used as a function decorator.
pop_all
()Transfers the callback stack to a fresh
ExitStack
instance and returns it. No callbacks are invoked by this operation - instead, they will now be invoked when the new stack is closed (either explicitly or implicitly at the end of awith
statement).For example, a group of files can be opened as an “all or nothing” operation as follows:
with ExitStack() as stack: files = [stack.enter_context(open(fname)) for fname in filenames] # Hold onto the close method, but don't call it yet. close_files = stack.pop_all().close # If opening any file fails, all previously opened files will be # closed automatically. If all files are opened successfully, # they will remain open even after the with statement ends. # close_files() can then be invoked explicitly to close them all.
close
()Immediately unwinds the callback stack, invoking callbacks in the reverse order of registration. For any context managers and exit callbacks registered, the arguments passed in will indicate that no exception occurred.
class contextlib.AsyncExitStack
An asynchronous context manager, similar to ExitStack
, that supports combining both synchronous and asynchronous context managers, as well as having coroutines for cleanup logic.
The close()
method is not implemented, aclose()
must be used instead.
coroutine
enter_async_context
(cm)Similar to
enter_context()
but expects an asynchronous context manager.push_async_exit
(exit)Similar to
push()
but expects either an asynchronous context manager or a coroutine function.push_async_callback
(callback, /, \args, *kwds)Similar to
callback()
but expects a coroutine function.coroutine
aclose
()Similar to
close()
but properly handles awaitables.
Continuing the example for asynccontextmanager()
:
async with AsyncExitStack() as stack:
connections = [await stack.enter_async_context(get_connection())
for i in range(5)]
# All opened connections will automatically be released at the end of
# the async with statement, even if attempts to open a connection
# later in the list raise an exception.
3.7 新版功能.
例子和配方
This section describes some examples and recipes for making effective use of the tools provided by contextlib
.
Supporting a variable number of context managers
The primary use case for ExitStack
is the one given in the class documentation: supporting a variable number of context managers and other cleanup operations in a single with
statement. The variability may come from the number of context managers needed being driven by user input (such as opening a user specified collection of files), or from some of the context managers being optional:
with ExitStack() as stack:
for resource in resources:
stack.enter_context(resource)
if need_special_resource():
special = acquire_special_resource()
stack.callback(release_special_resource, special)
# Perform operations that use the acquired resources
As shown, ExitStack
also makes it quite easy to use with
statements to manage arbitrary resources that don’t natively support the context management protocol.
Catching exceptions from __enter__
methods
It is occasionally desirable to catch exceptions from an __enter__
method implementation, without inadvertently catching exceptions from the with
statement body or the context manager’s __exit__
method. By using ExitStack
the steps in the context management protocol can be separated slightly in order to allow this:
stack = ExitStack()
try:
x = stack.enter_context(cm)
except Exception:
# handle __enter__ exception
else:
with stack:
# Handle normal case
Actually needing to do this is likely to indicate that the underlying API should be providing a direct resource management interface for use with try
/except
/finally
statements, but not all APIs are well designed in that regard. When a context manager is the only resource management API provided, then ExitStack
can make it easier to handle various situations that can’t be handled directly in a with
statement.
Cleaning up in an __enter__
implementation
As noted in the documentation of ExitStack.push()
, this method can be useful in cleaning up an already allocated resource if later steps in the __enter__()
implementation fail.
Here’s an example of doing this for a context manager that accepts resource acquisition and release functions, along with an optional validation function, and maps them to the context management protocol:
from contextlib import contextmanager, AbstractContextManager, ExitStack
class ResourceManager(AbstractContextManager):
def __init__(self, acquire_resource, release_resource, check_resource_ok=None):
self.acquire_resource = acquire_resource
self.release_resource = release_resource
if check_resource_ok is None:
def check_resource_ok(resource):
return True
self.check_resource_ok = check_resource_ok
@contextmanager
def _cleanup_on_error(self):
with ExitStack() as stack:
stack.push(self)
yield
# The validation check passed and didn't raise an exception
# Accordingly, we want to keep the resource, and pass it
# back to our caller
stack.pop_all()
def __enter__(self):
resource = self.acquire_resource()
with self._cleanup_on_error():
if not self.check_resource_ok(resource):
msg = "Failed validation for {!r}"
raise RuntimeError(msg.format(resource))
return resource
def __exit__(self, *exc_details):
# We don't need to duplicate any of our resource release logic
self.release_resource()
Replacing any use of try-finally
and flag variables
A pattern you will sometimes see is a try-finally
statement with a flag variable to indicate whether or not the body of the finally
clause should be executed. In its simplest form (that can’t already be handled just by using an except
clause instead), it looks something like this:
cleanup_needed = True
try:
result = perform_operation()
if result:
cleanup_needed = False
finally:
if cleanup_needed:
cleanup_resources()
As with any try
statement based code, this can cause problems for development and review, because the setup code and the cleanup code can end up being separated by arbitrarily long sections of code.
ExitStack
makes it possible to instead register a callback for execution at the end of a with
statement, and then later decide to skip executing that callback:
from contextlib import ExitStack
with ExitStack() as stack:
stack.callback(cleanup_resources)
result = perform_operation()
if result:
stack.pop_all()
This allows the intended cleanup up behaviour to be made explicit up front, rather than requiring a separate flag variable.
If a particular application uses this pattern a lot, it can be simplified even further by means of a small helper class:
from contextlib import ExitStack
class Callback(ExitStack):
def __init__(self, callback, /, *args, **kwds):
super().__init__()
self.callback(callback, *args, **kwds)
def cancel(self):
self.pop_all()
with Callback(cleanup_resources) as cb:
result = perform_operation()
if result:
cb.cancel()
If the resource cleanup isn’t already neatly bundled into a standalone function, then it is still possible to use the decorator form of ExitStack.callback()
to declare the resource cleanup in advance:
from contextlib import ExitStack
with ExitStack() as stack:
@stack.callback
def cleanup_resources():
...
result = perform_operation()
if result:
stack.pop_all()
Due to the way the decorator protocol works, a callback function declared this way cannot take any parameters. Instead, any resources to be released must be accessed as closure variables.
Using a context manager as a function decorator
ContextDecorator
makes it possible to use a context manager in both an ordinary with
statement and also as a function decorator.
For example, it is sometimes useful to wrap functions or groups of statements with a logger that can track the time of entry and time of exit. Rather than writing both a function decorator and a context manager for the task, inheriting from ContextDecorator
provides both capabilities in a single definition:
from contextlib import ContextDecorator
import logging
logging.basicConfig(level=logging.INFO)
class track_entry_and_exit(ContextDecorator):
def __init__(self, name):
self.name = name
def __enter__(self):
logging.info('Entering: %s', self.name)
def __exit__(self, exc_type, exc, exc_tb):
logging.info('Exiting: %s', self.name)
Instances of this class can be used as both a context manager:
with track_entry_and_exit('widget loader'):
print('Some time consuming activity goes here')
load_widget()
And also as a function decorator:
@track_entry_and_exit('widget loader')
def activity():
print('Some time consuming activity goes here')
load_widget()
Note that there is one additional limitation when using context managers as function decorators: there’s no way to access the return value of __enter__()
. If that value is needed, then it is still necessary to use an explicit with
statement.
参见
PEP 343 - “with” 语句
Python with
语句的规范描述、背景和示例。
Single use, reusable and reentrant context managers
Most context managers are written in a way that means they can only be used effectively in a with
statement once. These single use context managers must be created afresh each time they’re used - attempting to use them a second time will trigger an exception or otherwise not work correctly.
This common limitation means that it is generally advisable to create context managers directly in the header of the with
statement where they are used (as shown in all of the usage examples above).
Files are an example of effectively single use context managers, since the first with
statement will close the file, preventing any further IO operations using that file object.
Context managers created using contextmanager()
are also single use context managers, and will complain about the underlying generator failing to yield if an attempt is made to use them a second time:
>>> from contextlib import contextmanager
>>> @contextmanager
... def singleuse():
... print("Before")
... yield
... print("After")
...
>>> cm = singleuse()
>>> with cm:
... pass
...
Before
After
>>> with cm:
... pass
...
Traceback (most recent call last):
...
RuntimeError: generator didn't yield
Reentrant context managers
More sophisticated context managers may be “reentrant”. These context managers can not only be used in multiple with
statements, but may also be used inside a with
statement that is already using the same context manager.
threading.RLock
is an example of a reentrant context manager, as are suppress()
and redirect_stdout()
. Here’s a very simple example of reentrant use:
>>> from contextlib import redirect_stdout
>>> from io import StringIO
>>> stream = StringIO()
>>> write_to_stream = redirect_stdout(stream)
>>> with write_to_stream:
... print("This is written to the stream rather than stdout")
... with write_to_stream:
... print("This is also written to the stream")
...
>>> print("This is written directly to stdout")
This is written directly to stdout
>>> print(stream.getvalue())
This is written to the stream rather than stdout
This is also written to the stream
Real world examples of reentrancy are more likely to involve multiple functions calling each other and hence be far more complicated than this example.
Note also that being reentrant is not the same thing as being thread safe. redirect_stdout()
, for example, is definitely not thread safe, as it makes a global modification to the system state by binding sys.stdout
to a different stream.
Reusable context managers
Distinct from both single use and reentrant context managers are “reusable” context managers (or, to be completely explicit, “reusable, but not reentrant” context managers, since reentrant context managers are also reusable). These context managers support being used multiple times, but will fail (or otherwise not work correctly) if the specific context manager instance has already been used in a containing with statement.
threading.Lock
is an example of a reusable, but not reentrant, context manager (for a reentrant lock, it is necessary to use threading.RLock
instead).
Another example of a reusable, but not reentrant, context manager is ExitStack
, as it invokes all currently registered callbacks when leaving any with statement, regardless of where those callbacks were added:
>>> from contextlib import ExitStack
>>> stack = ExitStack()
>>> with stack:
... stack.callback(print, "Callback: from first context")
... print("Leaving first context")
...
Leaving first context
Callback: from first context
>>> with stack:
... stack.callback(print, "Callback: from second context")
... print("Leaving second context")
...
Leaving second context
Callback: from second context
>>> with stack:
... stack.callback(print, "Callback: from outer context")
... with stack:
... stack.callback(print, "Callback: from inner context")
... print("Leaving inner context")
... print("Leaving outer context")
...
Leaving inner context
Callback: from inner context
Callback: from outer context
Leaving outer context
As the output from the example shows, reusing a single stack object across multiple with statements works correctly, but attempting to nest them will cause the stack to be cleared at the end of the innermost with statement, which is unlikely to be desirable behaviour.
Using separate ExitStack
instances instead of reusing a single instance avoids that problem:
>>> from contextlib import ExitStack
>>> with ExitStack() as outer_stack:
... outer_stack.callback(print, "Callback: from outer context")
... with ExitStack() as inner_stack:
... inner_stack.callback(print, "Callback: from inner context")
... print("Leaving inner context")
... print("Leaving outer context")
...
Leaving inner context
Callback: from inner context
Leaving outer context
Callback: from outer context
abc
—- 抽象基类
源代码: Lib/abc.py
该模块提供了在 Python 中定义 抽象基类 (ABC) 的组件,在 PEP 3119 中已有概述。查看 PEP 文档了解为什么需要在 Python 中增加这个模块。(也可查看 PEP 3141 以及 numbers
模块了解基于 ABC 的数字类型继承关系。)
collections
模块中有一些派生自 ABC 的具体类;当然这些类还可以进一步被派生。此外,collections.abc
子模块中有一些 ABC 可被用于测试一个类或实例是否提供特定的接口,例如它是否可哈希或它是否为映射等。
该模块提供了一个元类 ABCMeta
,可以用来定义抽象类,另外还提供一个工具类 ABC
,可以用它以继承的方式定义抽象基类。
class abc.ABC
一个使用 ABCMeta
作为元类的工具类。抽象基类可以通过从 ABC
派生来简单地创建,这就避免了在某些情况下会令人混淆的元类用法,例如:
from abc import ABC
class MyABC(ABC):
pass
注意 ABC
的类型仍然是 ABCMeta
,因此继承 ABC
仍然需要关注元类使用中的注意事项,比如可能会导致元类冲突的多重继承。当然你也可以直接使用 ABCMeta
作为元类来定义抽象基类,例如:
from abc import ABCMeta
class MyABC(metaclass=ABCMeta):
pass
3.4 新版功能.
class abc.ABCMeta
用于定义抽象基类(ABC)的元类。
使用该元类以创建抽象基类。抽象基类可以像 mix-in 类一样直接被子类继承。你也可以将不相关的具体类(包括内建类)和抽象基类注册为“抽象子类” —— 这些类以及它们的子类会被内建函数 issubclass()
识别为对应的抽象基类的子类,但是该抽象基类不会出现在其 MRO(Method Resolution Order,方法解析顺序)中,抽象基类中实现的方法也不可调用(即使通过 super()
调用也不行)。
使用 ABCMeta
作为元类创建的类含有如下方法:
register
(subclass)将“子类”注册为该抽象基类的“抽象子类”,例如:
from abc import ABC class MyABC(ABC): pass MyABC.register(tuple) assert issubclass(tuple, MyABC) assert isinstance((), MyABC)
在 3.3 版更改: 返回注册的子类,使其能够作为类装饰器。
在 3.4 版更改: 你可以使用
get_cache_token()
函数来检测对register()
的调用。
你也可以在虚基类中重载这个方法。
__subclasshook__
(subclass)(必须定义为类方法。)
检查 subclass 是否是该抽象基类的子类。也就是说对于那些你希望定义为该抽象基类的子类的类,你不用对每个类都调用
register()
方法了,而是可以直接自定义issubclass
的行为。(这个类方法是在抽象基类的__subclasscheck__()
方法中调用的。)该方法必须返回
True
,False
或是NotImplemented
。如果返回True
,subclass 就会被认为是这个抽象基类的子类。如果返回False
,无论正常情况是否应该认为是其子类,统一视为不是。如果返回NotImplemented
,子类检查会按照正常机制继续执行。
为了对这些概念做一演示,请看以下定义 ABC 的示例:
class Foo:
def __getitem__(self, index):
...
def __len__(self):
...
def get_iterator(self):
return iter(self)
class MyIterable(ABC):
@abstractmethod
def __iter__(self):
while False:
yield None
def get_iterator(self):
return self.__iter__()
@classmethod
def __subclasshook__(cls, C):
if cls is MyIterable:
if any("__iter__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
MyIterable.register(Foo)
ABC MyIterable
定义了标准的迭代方法 __iter__()
作为一个抽象方法。这里给出的实现仍可在子类中被调用。get_iterator()
方法也是 MyIterable
抽象基类的一部分,但它并非必须被非抽象派生类所重载。
这里定义的 __subclasshook__()
类方法指明了任何在其 __dict__
(或在其通过 __mro__
列表访问的基类) 中具有 __iter__()
方法的类也都会被视为 MyIterable
。
最后,末尾行使得 Foo
成为 MyIterable
的一个虚子类,即使它没有定义 __iter__()
方法(它使用了以 __len__()
和 __getitem__()
术语定义的旧式可迭代对象协议)。 请注意这将不会使 get_iterator
成为 Foo
的一个可用方法,它是被另外提供的。
此外,abc
模块还提供了这些装饰器:
@``abc.abstractmethod
用于声明抽象方法的装饰器。
使用此装饰器要求类的元类是 ABCMeta
或是从该类派生。一个具有派生自 ABCMeta
的元类的类不可以被实例化,除非它全部的抽象方法和特征属性均已被重载。抽象方法可通过任何普通的“super”调用机制来调用。 abstractmethod()
可被用于声明特性属性和描述器的抽象方法。
动态地添加抽象方法到一个类,或尝试在方法或类被创建后修改其抽象状态等操作仅在使用 update_abstractmethods()
函数时受到支持。 abstractmethod()
只会影响使用常规继承所派生的子类;通过 ABC 的 register()
方法注册的“虚子类”不会受到影响。
当 abstractmethod()
与其他方法描述符配合应用时,它应当被应用为最内层的装饰器,如以下用法示例所示:
class C(ABC):
@abstractmethod
def my_abstract_method(self, ...):
...
@classmethod
@abstractmethod
def my_abstract_classmethod(cls, ...):
...
@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):
...
@property
@abstractmethod
def my_abstract_property(self):
...
@my_abstract_property.setter
@abstractmethod
def my_abstract_property(self, val):
...
@abstractmethod
def _get_x(self):
...
@abstractmethod
def _set_x(self, val):
...
x = property(_get_x, _set_x)
为了能正确地与抽象基类机制实现互操作,描述符必须使用 __isabstractmethod__
将自身标识为抽象的。 通常,如果被用于组成描述符的任何方法都是抽象的则此属性应当为 True
。 例如,Python 的内置 property
所做的就等价于:
class Descriptor:
...
@property
def __isabstractmethod__(self):
return any(getattr(f, '__isabstractmethod__', False) for
f in (self._fget, self._fset, self._fdel))
注解
不同于 Java 抽象方法,这些抽象方法可能具有一个实现。 这个实现可在重载它的类上通过 super()
机制来调用。 这在使用协作多重继承的框架中可以被用作超调用的一个端点。
abc
模块还支持下列旧式装饰器:
@``abc.abstractclassmethod
3.2 新版功能.
3.3 版后已移除: 现在可以让 classmethod
配合 abstractmethod()
使用,使得此装饰器变得冗余。
内置 classmethod()
的子类,指明一个抽象类方法。 在其他方面它都类似于 abstractmethod()
。
这个特例已被弃用,因为现在当 classmethod()
装饰器应用于抽象方法时它会被正确地标识为抽象的:
class C(ABC):
@classmethod
@abstractmethod
def my_abstract_classmethod(cls, ...):
...
3.2 新版功能.
3.3 版后已移除: 现在可以让 staticmethod
配合 abstractmethod()
使用,使得此装饰器变得冗余。
内置 staticmethod()
的子类,指明一个抽象静态方法。 在其他方面它都类似于 abstractmethod()
。
这个特例已被弃用,因为现在当 staticmethod()
装饰器应用于抽象方法时它会被正确地标识为抽象的:
class C(ABC):
@staticmethod
@abstractmethod
def my_abstract_staticmethod(...):
...
3.3 版后已移除: 现在可以让 property
, property.getter()
, property.setter()
和 property.deleter()
配合 abstractmethod()
使用,使得此装饰器变得冗余。
内置 property()
的子类,指明一个抽象特性属性。
这个特例已被弃用,因为现在当 property()
装饰器应用于抽象方法时它会被正确地标识为抽象的:
class C(ABC):
@property
@abstractmethod
def my_abstract_property(self):
...
上面的例子定义了一个只读特征属性;你也可以通过适当地将一个或多个下层方法标记为抽象的来定义可读写的抽象特征属性:
class C(ABC):
@property
def x(self):
...
@x.setter
@abstractmethod
def x(self, val):
...
如果只有某些组件是抽象的,则只需更新那些组件即可在子类中创建具体的特征属性:
class D(C):
@C.x.setter
def x(self, val):
...
abc
模块还提供了这些函数:
abc.get_cache_token
()
返回当前抽象基类的缓存令牌
此令牌是一个不透明对象(支持相等性测试),用于为虚子类标识抽象基类缓存的当前版本。 此令牌会在任何 ABC 上每次调用 ABCMeta.register()
时发生更改。
3.4 新版功能.
abc.update_abstractmethods
(cls)
重新计算一个抽象类的抽象状态的函数。 如果一个类的抽象方法在类被创建后被实现或被修改则应当调用此函数。 通常,此函数应当在一个类装饰器内部被调用。
返回 cls,使其能够用作类装饰器。
如果 cls 不是 ABCMeta
的子类,则不做任何操作。
注解
此函数会假定 cls 的上级类已经被更新。 它不会更新任何子类。
3.10 新版功能.
atexit
—- 退出处理器
atexit
模块定义了清理函数的注册和反注册函数. 被注册的函数会在解释器正常终止时执行. atexit
会按照注册顺序的逆序执行; 如果你注册了 A
, B
和 C
, 那么在解释器终止时会依序执行 C
, B
, A
.
注意: 通过该模块注册的函数, 在程序被未被 Python 捕获的信号杀死时并不会执行, 在检测到 Python 内部致命错误以及调用了 os._exit()
时也不会执行.
在 3.7 版更改: 当配合 C-API 子解释器使用时,已注册函数是它们所注册解释器中的局部对象。
atexit.register
(func, \args, *kwargs)
将 func 注册为终止时执行的函数. 任何传给 func 的可选的参数都应当作为参数传给 register()
. 可以多次注册同样的函数及参数.
在正常的程序终止时 (举例来说, 当调用了 sys.exit()
或是主模块的执行完成时), 所有注册过的函数都会以后进先出的顺序执行. 这样做是假定更底层的模块通常会比高层模块更早引入, 因此需要更晚清理.
如果在 exit 处理句柄执行期间引发了异常,将会打印回溯信息 (除非引发的是 SystemExit
) 并且异常信息会被保存。 在所有 exit 处理句柄都获得运行机会之后,所引发的最后一个异常会被重新引发。
这个函数返回 func 对象,可以把它当作装饰器使用。
atexit.unregister
(func)
将 func 移出当解释器关闭时要运行的函数列表。 如果 func 之前未被注册则 unregister()
将静默地不做任何事。 如果 func 已被注册一次以上,则该函数每次在 atexit
调用栈中的出现都将被移除。 当取消注册时会在内部使用相等性比较 (==
),因而函数引用不需要具有匹配的标识号。
atexit
示例
以下简单例子演示了一个模块在被导入时如何从文件初始化一个计数器,并在程序终结时自动保存计数器的更新值,此操作不依赖于应用在终结时对此模块进行显式调用。:
try:
with open('counterfile') as infile:
_count = int(infile.read())
except FileNotFoundError:
_count = 0
def incrcounter(n):
global _count
_count = _count + n
def savecounter():
with open('counterfile', 'w') as outfile:
outfile.write('%d' % _count)
import atexit
atexit.register(savecounter)
位置和关键字参数也可传入 register()
以便传递给被调用的已注册函数:
def goodbye(name, adjective):
print('Goodbye %s, it was %s to meet you.' % (name, adjective))
import atexit
atexit.register(goodbye, 'Donny', 'nice')
# or:
atexit.register(goodbye, adjective='nice', name='Donny')
作为 decorator: 使用:
import atexit
@atexit.register
def goodbye():
print('You are now leaving the Python sector.')
只有在函数不需要任何参数调用时才能工作.
traceback
—- 打印或检索堆栈回溯
源代码: Lib/traceback.py
该模块提供了一个标准接口来提取、格式化和打印 Python 程序的堆栈跟踪结果。它完全模仿Python 解释器在打印堆栈跟踪结果时的行为。当您想要在程序控制下打印堆栈跟踪结果时,例如在“封装”解释器时,这是非常有用的。
这个模块使用 traceback 对象 —— 这是存储在 sys.last_traceback
中的对象类型变量,并作为 sys.exc_info()
的第三项被返回。
这个模块定义了以下函数:
traceback.print_tb
(tb, limit=None, file=None)
如果limit*是正整数,那么从 traceback 对象 “tb” 输出最高 *limit 个(从调用函数开始的)栈的堆栈回溯条目;如果 limit 是负数就输出 abs(limit)
个回溯条目;又如果 limit 被省略或者为 None
,那么就会输出所有回溯条目。如果 file 被省略或为 None
那么就会输出至标准输出sys.stderr
否则它应该是一个打开的文件或者文件类对象来接收输出
在 3.5 版更改: 添加了对负数值 limit 的支持
traceback.print_exception
(exc, /, [value, tb, ]limit=None, file=None, chain=True)
打印回溯对象 tb 到 file 的异常信息和整个堆栈回溯。这和 print_tb()
比有以下方面不同:
- 如果 tb 不为
None
,它将打印头部Traceback (most recent call last):
- it prints the exception type and value after the stack trace
- if type(value) is
SyntaxError
and value has the appropriate format, it prints the line where the syntax error occurred with a caret indicating the approximate position of the error.
Since Python 3.10, instead of passing value and tb, an exception object can be passed as the first argument. If value and tb are provided, the first argument is ignored in order to provide backwards compatibility.
The optional limit argument has the same meaning as for print_tb()
. If chain is true (the default), then chained exceptions (the __cause__
or __context__
attributes of the exception) will be printed as well, like the interpreter itself does when printing an unhandled exception.
在 3.5 版更改: The etype argument is ignored and inferred from the type of value.
在 3.10 版更改: The etype parameter has been renamed to exc and is now positional-only.
traceback.print_exc
(limit=None, file=None, chain=True)
This is a shorthand for print_exception(*sys.exc_info(), limit, file, chain)
.
traceback.print_last
(limit=None, file=None, chain=True)
This is a shorthand for print_exception(sys.last_type, sys.last_value, sys.last_traceback, limit, file, chain)
. In general it will work only after an exception has reached an interactive prompt (see sys.last_type
).
traceback.print_stack
(f=None, limit=None, file=None)
Print up to limit stack trace entries (starting from the invocation point) if limit is positive. Otherwise, print the last abs(limit)
entries. If limit is omitted or None
, all entries are printed. The optional f argument can be used to specify an alternate stack frame to start. The optional file argument has the same meaning as for print_tb()
.
在 3.5 版更改: 添加了对负数值 limit 的支持
traceback.extract_tb
(tb, limit=None)
Return a StackSummary
object representing a list of “pre-processed” stack trace entries extracted from the traceback object tb. It is useful for alternate formatting of stack traces. The optional limit argument has the same meaning as for print_tb()
. A “pre-processed” stack trace entry is a FrameSummary
object containing attributes filename
, lineno
, name
, and line
representing the information that is usually printed for a stack trace. The line
is a string with leading and trailing whitespace stripped; if the source is not available it is None
.
traceback.extract_stack
(f=None, limit=None)
Extract the raw traceback from the current stack frame. The return value has the same format as for extract_tb()
. The optional f and limit arguments have the same meaning as for print_stack()
.
traceback.format_list
(extracted_list)
Given a list of tuples or FrameSummary
objects as returned by extract_tb()
or extract_stack()
, return a list of strings ready for printing. Each string in the resulting list corresponds to the item with the same index in the argument list. Each string ends in a newline; the strings may contain internal newlines as well, for those items whose source text line is not None
.
traceback.format_exception_only
(exc, /[, value])
Format the exception part of a traceback using an exception value such as given by sys.last_value
. The return value is a list of strings, each ending in a newline. Normally, the list contains a single string; however, for SyntaxError
exceptions, it contains several lines that (when printed) display detailed information about where the syntax error occurred. The message indicating which exception occurred is the always last string in the list.
Since Python 3.10, instead of passing value, an exception object can be passed as the first argument. If value is provided, the first argument is ignored in order to provide backwards compatibility.
在 3.10 版更改: The etype parameter has been renamed to exc and is now positional-only.
traceback.format_exception
(exc, /, [value, tb, ]limit=None, chain=True)
Format a stack trace and the exception information. The arguments have the same meaning as the corresponding arguments to print_exception()
. The return value is a list of strings, each ending in a newline and some containing internal newlines. When these lines are concatenated and printed, exactly the same text is printed as does print_exception()
.
在 3.5 版更改: The etype argument is ignored and inferred from the type of value.
在 3.10 版更改: This function’s behavior and signature were modified to match print_exception()
.
traceback.format_exc
(limit=None, chain=True)
This is like print_exc(limit)
but returns a string instead of printing to a file.
traceback.format_tb
(tb, limit=None)
A shorthand for format_list(extract_tb(tb, limit))
.
traceback.format_stack
(f=None, limit=None)
A shorthand for format_list(extract_stack(f, limit))
.
traceback.clear_frames
(tb)
Clears the local variables of all the stack frames in a traceback tb by calling the clear()
method of each frame object.
3.4 新版功能.
traceback.walk_stack
(f)
Walk a stack following f.f_back
from the given frame, yielding the frame and line number for each frame. If f is None
, the current stack is used. This helper is used with StackSummary.extract()
.
3.5 新版功能.
traceback.walk_tb
(tb)
Walk a traceback following tb_next
yielding the frame and line number for each frame. This helper is used with StackSummary.extract()
.
3.5 新版功能.
The module also defines the following classes:
TracebackException
Objects
3.5 新版功能.
TracebackException
objects are created from actual exceptions to capture data for later printing in a lightweight fashion.
class traceback.TracebackException
(exc_type, exc_value, exc_traceback, **, limit=None, lookup_lines=True, capture_locals=False, compact=False*)
Capture an exception for later rendering. limit, lookup_lines and capture_locals are as for the StackSummary
class.
If compact is true, only data that is required by TracebackException
‘s format
method is saved in the class attributes. In particular, the __context__
field is calculated only if __cause__
is None
and __suppress_context__
is false.
Note that when locals are captured, they are also shown in the traceback.
__cause__
A
TracebackException
of the original__cause__
.__context__
A
TracebackException
of the original__context__
.__suppress_context__
The
__suppress_context__
value from the original exception.stack
A
StackSummary
representing the traceback.exc_type
The class of the original traceback.
filename
For syntax errors - the file name where the error occurred.
lineno
For syntax errors - the line number where the error occurred.
text
For syntax errors - the text where the error occurred.
offset
For syntax errors - the offset into the text where the error occurred.
msg
For syntax errors - the compiler error message.
classmethod
from_exception
(exc, **, limit=None, lookup_lines=True, capture_locals=False*)Capture an exception for later rendering. limit, lookup_lines and capture_locals are as for the
StackSummary
class.Note that when locals are captured, they are also shown in the traceback.
format
(**, chain=True*)Format the exception.
If chain is not
True
,__cause__
and__context__
will not be formatted.The return value is a generator of strings, each ending in a newline and some containing internal newlines.
print_exception()
is a wrapper around this method which just prints the lines to a file.The message indicating which exception occurred is always the last string in the output.
format_exception_only
()Format the exception part of the traceback.
The return value is a generator of strings, each ending in a newline.
Normally, the generator emits a single string; however, for
SyntaxError
exceptions, it emits several lines that (when printed) display detailed information about where the syntax error occurred.The message indicating which exception occurred is always the last string in the output.
在 3.10 版更改: 增加了 compact 形参。
StackSummary
Objects
3.5 新版功能.
StackSummary
objects represent a call stack ready for formatting.
class traceback.StackSummary
classmethod
extract
(frame_gen, **, limit=None, lookup_lines=True, capture_locals=False*)Construct a
StackSummary
object from a frame generator (such as is returned bywalk_stack()
orwalk_tb()
).If limit is supplied, only this many frames are taken from frame_gen. If lookup_lines is
False
, the returnedFrameSummary
objects will not have read their lines in yet, making the cost of creating theStackSummary
cheaper (which may be valuable if it may not actually get formatted). If capture_locals isTrue
the local variables in eachFrameSummary
are captured as object representations.classmethod
from_list
(a_list)Construct a
StackSummary
object from a supplied list ofFrameSummary
objects or old-style list of tuples. Each tuple should be a 4-tuple with filename, lineno, name, line as the elements.format
()Returns a list of strings ready for printing. Each string in the resulting list corresponds to a single frame from the stack. Each string ends in a newline; the strings may contain internal newlines as well, for those items with source text lines.
For long sequences of the same frame and line, the first few repetitions are shown, followed by a summary line stating the exact number of further repetitions.
在 3.6 版更改: Long sequences of repeated frames are now abbreviated.
FrameSummary
Objects
3.5 新版功能.
FrameSummary
objects represent a single frame in a traceback.
class traceback.FrameSummary
(filename, lineno, name, lookup_line=True, locals=None, line=None)
Represent a single frame in the traceback or stack that is being formatted or printed. It may optionally have a stringified version of the frames locals included in it. If lookup_line is False
, the source code is not looked up until the FrameSummary
has the line
attribute accessed (which also happens when casting it to a tuple). line
may be directly provided, and will prevent line lookups happening at all. locals is an optional local variable dictionary, and if supplied the variable representations are stored in the summary for later display.
Traceback Examples
This simple example implements a basic read-eval-print loop, similar to (but less useful than) the standard Python interactive interpreter loop. For a more complete implementation of the interpreter loop, refer to the code
module.
import sys, traceback
def run_user_code(envdir):
source = input(">>> ")
try:
exec(source, envdir)
except Exception:
print("Exception in user code:")
print("-"*60)
traceback.print_exc(file=sys.stdout)
print("-"*60)
envdir = {}
while True:
run_user_code(envdir)
The following example demonstrates the different ways to print and format the exception and traceback:
import sys, traceback
def lumberjack():
bright_side_of_death()
def bright_side_of_death():
return tuple()[0]
try:
lumberjack()
except IndexError:
exc_type, exc_value, exc_traceback = sys.exc_info()
print("*** print_tb:")
traceback.print_tb(exc_traceback, limit=1, file=sys.stdout)
print("*** print_exception:")
# exc_type below is ignored on 3.5 and later
traceback.print_exception(exc_type, exc_value, exc_traceback,
limit=2, file=sys.stdout)
print("*** print_exc:")
traceback.print_exc(limit=2, file=sys.stdout)
print("*** format_exc, first and last line:")
formatted_lines = traceback.format_exc().splitlines()
print(formatted_lines[0])
print(formatted_lines[-1])
print("*** format_exception:")
# exc_type below is ignored on 3.5 and later
print(repr(traceback.format_exception(exc_type, exc_value,
exc_traceback)))
print("*** extract_tb:")
print(repr(traceback.extract_tb(exc_traceback)))
print("*** format_tb:")
print(repr(traceback.format_tb(exc_traceback)))
print("*** tb_lineno:", exc_traceback.tb_lineno)
The output for the example would look similar to this:
*** print_tb:
File "<doctest...>", line 10, in <module>
lumberjack()
*** print_exception:
Traceback (most recent call last):
File "<doctest...>", line 10, in <module>
lumberjack()
File "<doctest...>", line 4, in lumberjack
bright_side_of_death()
IndexError: tuple index out of range
*** print_exc:
Traceback (most recent call last):
File "<doctest...>", line 10, in <module>
lumberjack()
File "<doctest...>", line 4, in lumberjack
bright_side_of_death()
IndexError: tuple index out of range
*** format_exc, first and last line:
Traceback (most recent call last):
IndexError: tuple index out of range
*** format_exception:
['Traceback (most recent call last):\n',
' File "<doctest...>", line 10, in <module>\n lumberjack()\n',
' File "<doctest...>", line 4, in lumberjack\n bright_side_of_death()\n',
' File "<doctest...>", line 7, in bright_side_of_death\n return tuple()[0]\n',
'IndexError: tuple index out of range\n']
*** extract_tb:
[<FrameSummary file <doctest...>, line 10 in <module>>,
<FrameSummary file <doctest...>, line 4 in lumberjack>,
<FrameSummary file <doctest...>, line 7 in bright_side_of_death>]
*** format_tb:
[' File "<doctest...>", line 10, in <module>\n lumberjack()\n',
' File "<doctest...>", line 4, in lumberjack\n bright_side_of_death()\n',
' File "<doctest...>", line 7, in bright_side_of_death\n return tuple()[0]\n']
*** tb_lineno: 10
The following example shows the different ways to print and format the stack:
>>> import traceback
>>> def another_function():
... lumberstack()
...
>>> def lumberstack():
... traceback.print_stack()
... print(repr(traceback.extract_stack()))
... print(repr(traceback.format_stack()))
...
>>> another_function()
File "<doctest>", line 10, in <module>
another_function()
File "<doctest>", line 3, in another_function
lumberstack()
File "<doctest>", line 6, in lumberstack
traceback.print_stack()
[('<doctest>', 10, '<module>', 'another_function()'),
('<doctest>', 3, 'another_function', 'lumberstack()'),
('<doctest>', 7, 'lumberstack', 'print(repr(traceback.extract_stack()))')]
[' File "<doctest>", line 10, in <module>\n another_function()\n',
' File "<doctest>", line 3, in another_function\n lumberstack()\n',
' File "<doctest>", line 8, in lumberstack\n print(repr(traceback.format_stack()))\n']
This last example demonstrates the final few formatting functions:
>>> import traceback
>>> traceback.format_list([('spam.py', 3, '<module>', 'spam.eggs()'),
... ('eggs.py', 42, 'eggs', 'return "bacon"')])
[' File "spam.py", line 3, in <module>\n spam.eggs()\n',
' File "eggs.py", line 42, in eggs\n return "bacon"\n']
>>> an_error = IndexError('tuple index out of range')
>>> traceback.format_exception_only(type(an_error), an_error)
['IndexError: tuple index out of range\n']
__future__
—- Future 语句定义
源代码: Lib/future.py
__future__
是一个真正的模块,这主要有 3 个原因:
- 避免混淆已有的分析 import 语句并查找 import 的模块的工具。
- 确保 future 语句 在 2.1 之前的版本运行时至少能抛出 runtime 异常(import
__future__
会失败,因为 2.1 版本之前没有这个模块)。 - 当引入不兼容的修改时,可以记录其引入的时间以及强制使用的时间。这是一种可执行的文档,并且可以通过 import
__future__
来做程序性的检查。
__future__.py
中的每一条语句都是以下格式的:
FeatureName = _Feature(OptionalRelease, MandatoryRelease,
CompilerFlag)
通常 OptionalRelease 要比 MandatoryRelease 小,并且都是和 sys.version_info
格式一致的 5 元素元组。
(PY_MAJOR_VERSION, # the 2 in 2.1.0a3; an int
PY_MINOR_VERSION, # the 1; an int
PY_MICRO_VERSION, # the 0; an int
PY_RELEASE_LEVEL, # "alpha", "beta", "candidate" or "final"; string
PY_RELEASE_SERIAL # the 3; an int
)
OptionalRelease 记录了一个特性首次发布时的 Python 版本。
在 MandatoryRelases 还没有发布时,MandatoryRelease 表示该特性会变成语言的一部分的预测时间。
其他情况下,MandatoryRelease 用来记录这个特性是何时成为语言的一部分的。从该版本往后,使用该特性将不需要 future 语句,不过很多人还是会加上对应的 import。
MandatoryRelease 也可能是 None
, 表示这个特性已经被撤销。
_Feature
类的实例有两个对应的方法,getOptionalRelease()
和 getMandatoryRelease()
。
CompilerFlag 是一个(位)标记,对于动态编译的代码,需要将这个标记作为第四个参数传入内建函数 compile()
中以开启对应的特性。这个标记存储在 _Feature
类实例的 compiler_flag
属性中。
__future__
中不会删除特性的描述。从 Python 2.1 中首次加入以来,通过这种方式引入了以下特性:
特性 | 可选版本 | 强制加入版本 | 效果 |
---|---|---|---|
nested_scopes | 2.1.0b1 | 2.2 | PEP 227: 静态嵌套作用域 |
generators | 2.2.0a1 | 2.3 | PEP 255: 简单生成器 |
division | 2.2.0a2 | 3.0 | PEP 238: 修改除法运算符 |
absolute_import | 2.5.0a1 | 3.0 | PEP 328: 导入:多行与绝对/相对 |
with_statement | 2.5.0a1 | 2.6 | PEP 343: “with” 语句 |
print_function | 2.6.0a2 | 3.0 | PEP 3105: print 改为函数 |
unicode_literals | 2.6.0a2 | 3.0 | PEP 3112: Python 3000 中的字节字面值 |
generator_stop | 3.5.0b1 | 3.7 | PEP 479: 在生成器中处理 StopIteration |
annotations | 3.7.0b1 | 3.11 | PEP 563: Postponed evaluation of annotations |
参见
future 语句
编译器怎样处理 future import。
gc
—- 垃圾回收器接口
此模块提供可选的垃圾回收器的接口,提供的功能包括:关闭收集器、调整收集频率、设置调试选项。它同时提供对回收器找到但是无法释放的不可达对象的访问。由于 Python 使用了带有引用计数的回收器,如果你确定你的程序不会产生循环引用,你可以关闭回收器。可以通过调用 gc.disable()
关闭自动垃圾回收。若要调试一个存在内存泄漏的程序,调用 gc.set_debug(gc.DEBUG_LEAK)
;需要注意的是,它包含 gc.DEBUG_SAVEALL
,使得被垃圾回收的对象会被存放在 gc.garbage 中以待检查。
gc
模块提供下列函数:
gc.enable
()
启用自动垃圾回收
gc.disable
()
停用自动垃圾回收
gc.isenabled
()
如果启用了自动回收则返回 True
。
gc.collect
(generation=2)
若被调用时不包含参数,则启动完全的垃圾回收。可选的参数 generation 可以是一个整数,指明需要回收哪一代(从 0 到 2 )的垃圾。当参数 generation 无效时,会引发 ValueError
异常。返回发现的不可达对象的数目。
每当运行完整收集或最高代 (2) 收集时,为多个内置类型所维护的空闲列表会被清空。 由于特定类型特别是 float
的实现,在某些空闲列表中并非所有项都会被释放。
gc.set_debug
(flags)
设置垃圾回收器的调试标识位。调试信息会被写入 sys.stderr
。此文档末尾列出了各个标志位及其含义;可以使用位操作对多个标志位进行设置以控制调试器。
gc.get_debug
()
返回当前调试标识位。
gc.get_objects
(generation=None)
返回一个收集器所跟踪的所有对象的列表,所返回的列表除外。 如果 generation 不为 None,则只返回收集器所跟踪的属于该生成的对象。
在 3.8 版更改: 新的 generation 形参。
引发一个 审计事件 gc.get_objects
,附带参数 generation
。
gc.get_stats
()
返回一个包含三个字典对象的列表,每个字典分别包含对应代的从解释器开始运行的垃圾回收统计数据。字典的键的数目在将来可能发生改变,目前每个字典包含以下内容:
collections
是该代被回收的次数;collected
是该代中被回收的对象总数;uncollectable
是在这一代中被发现无法收集的对象总数 (因此被移动到garbage
列表中)。
3.4 新版功能.
gc.set_threshold
(threshold0[, threshold1[, threshold2]])
设置垃圾回收阈值(收集频率)。 将 threshold0 设为零会禁用回收。
垃圾回收器把所有对象分类为三代,其依据是对象在多少次垃圾回收后幸存。 新建对象会被放在最年轻代(第 0
代)。 如果一个对象在一次垃圾回收后幸存,它会被移入下一个较老代。 由于第 2
代是最老代,这一代的对象在一次垃圾回收后仍会保留原样。 为了确定何时要运行,垃圾回收器会跟踪自上一次回收后对象分配和释放的数量。 当分配数量减去释放数量的结果值大于 threshold0 时,垃圾回收就会开始。 初始时只有第 0
代会被检查。 如果自第 1
代被检查后第 0
代已被检查超过 threshold1 次,则第 1
也会被检查。 对于第三代来说情况还会更复杂。
gc.get_count
()
将当前回收计数以形为 (count0, count1, count2)
的元组返回。
gc.get_threshold
()
将当前回收阈值以形为 (threshold0, threshold1, threshold2)
的元组返回。
gc.get_referrers
(\objs*)
返回直接引用任意一个 ojbs 的对象列表。这个函数只定位支持垃圾回收的容器;引用了其它对象但不支持垃圾回收的扩展类型不会被找到。
需要注意的是,已经解除对 objs 引用的对象,但仍存在于循环引用中未被回收时,仍然会被作为引用者出现在返回的列表当中。若要获取当前正在引用 objs 的对象,需要调用 collect()
然后再调用 get_referrers()
。
警告
在使用 get_referrers()
返回的对象时必须要小心,因为其中一些对象可能仍在构造中因此处于暂时的无效状态。不要把 get_referrers()
用于调试以外的其它目的。
引发一个 审计事件 gc.get_referrers
,附带参数 objs
。
gc.get_referents
(\objs*)
返回被任意一个参数中的对象直接引用的对象的列表。返回的被引用对象是被参数中的对象的C语言级别方法(若存在) tp_traverse
访问到的对象,可能不是所有的实际直接可达对象。只有支持垃圾回收的对象支持 tp_traverse
方法,并且此方法只会在需要访问涉及循环引用的对象时使用。因此,可以有以下例子:一个整数对其中一个参数是直接可达的,这个整数有可能出现或不出现在返回的结果列表当中。
引发一个 审计事件 gc.get_referents
,附带参数 objs
。
gc.is_tracked
(obj)
当对象正在被垃圾回收器监控时返回 True
,否则返回 False
。一般来说,原子类的实例不会被监控,而非原子类(如容器、用户自定义的对象)会被监控。然而,会有一些特定类型的优化以便减少垃圾回收器在简单实例(如只含有原子性的键和值的字典)上的消耗。
>>> gc.is_tracked(0)
False
>>> gc.is_tracked("a")
False
>>> gc.is_tracked([])
True
>>> gc.is_tracked({})
False
>>> gc.is_tracked({"a": 1})
False
>>> gc.is_tracked({"a": []})
True
3.1 新版功能.
gc.is_finalized
(obj)
如果给定对象已被垃圾回收器终结则返回 True
,否则返回 False
。
>>> x = None
>>> class Lazarus:
... def __del__(self):
... global x
... x = self
...
>>> lazarus = Lazarus()
>>> gc.is_finalized(lazarus)
False
>>> del lazarus
>>> gc.is_finalized(x)
True
3.9 新版功能.
gc.freeze
()
冻结 gc 所跟踪的所有对象 —— 将它们移至永久代并忽略所有未来的集合。 这可以在 POSIX fork() 调用之前使用以便令对写入复制保持友好或加速收集。 并且在 POSIX fork() 调用之前的收集也可以释放页面以供未来分配,这也可能导致写入时复制,因此建议在主进程中禁用 gc 并在 fork 之前冻结,而在子进程中启用 gc。
3.7 新版功能.
gc.unfreeze
()
解冻永久代中的对象,并将它们放回到年老代中。
3.7 新版功能.
gc.get_freeze_count
()
返回永久代中的对象数量。
3.7 新版功能.
提供以下变量仅供只读访问(你可以修改但不应该重绑定它们):
gc.garbage
一个回收器发现不可达而又无法被释放的对象(不可回收对象)列表。 从 Python 3.4 开始,该列表在大多数时候都应该是空的,除非使用了含有非 NULL
tp_del
空位的 C 扩展类型的实例。
如果设置了 DEBUG_SAVEALL
,则所有不可访问对象将被添加至该列表而不会被释放。
在 3.2 版更改: 当 interpreter shutdown 即解释器关闭时,若此列表非空,会产生 ResourceWarning
,即资源警告,在默认情况下此警告不会被提醒。如果设置了 DEBUG_UNCOLLECTABLE
,所有无法被回收的对象会被打印。
在 3.4 版更改: 根据 PEP 442 ,带有 __del__()
方法的对象最终不再会进入 gc.garbage
。
gc.callbacks
在垃圾回收器开始前和完成后会被调用的一系列回调函数。这些回调函数在被调用时使用两个参数: phase 和 info 。
phase 可为以下两值之一:
“start”: 垃圾回收即将开始。
“stop”: 垃圾回收已结束。
info is a dict providing more information for the callback. The following keys are currently defined:
“generation”(代) :正在被回收的最久远的一代。
“collected”(已回收的 ): 当phase 为 “stop” 时,被成功回收的对象的数目。
“uncollectable”(不可回收的): 当 phase 为 “stop” 时,不能被回收并被放入
garbage
的对象的数目。
应用程序可以把他们自己的回调函数加入此列表。主要的使用场景有:
统计垃圾回收的数据,如:不同代的回收频率、回收所花费的时间。
使应用程序可以识别和清理他们自己的在
garbage
中的不可回收类型的对象。
3.3 新版功能.
以下常量被用于 set_debug()
:
gc.DEBUG_STATS
在回收完成后打印统计信息。当回收频率设置较高时,这些信息会比较有用。
gc.DEBUG_COLLECTABLE
当发现可回收对象时打印信息。
gc.DEBUG_UNCOLLECTABLE
打印找到的不可回收对象的信息(指不能被回收器回收的不可达对象)。这些对象会被添加到 garbage
列表中。
在 3.2 版更改: 当 interpreter shutdown 时,即解释器关闭时,若 garbage
列表中存在对象,这些对象也会被打印输出。
gc.DEBUG_SAVEALL
设置后,所有回收器找到的不可达对象会被添加进 garbage 而不是直接被释放。这在调试一个内存泄漏的程序时会很有用。
gc.DEBUG_LEAK
调试内存泄漏的程序时,使回收器打印信息的调试标识位。(等价于 DEBUG_COLLECTABLE | DEBUG_UNCOLLECTABLE | DEBUG_SAVEALL
)。
inspect
—- 检查对象
源代码: Lib/inspect.py
inspect
模块提供了一些有用的函数帮助获取对象的信息,例如模块、类、方法、函数、回溯、帧对象以及代码对象。例如它可以帮助你检查类的内容,获取某个方法的源代码,取得并格式化某个函数的参数列表,或者获取你需要显示的回溯的详细信息。
该模块提供了4种主要的功能:类型检查、获取源代码、检查类与函数、检查解释器的调用堆栈。
类型和成员
getmembers()
函数获取对象的成员,例如类或模块。函数名以”is”开始的函数主要作为 getmembers()
的第2个参数使用。它们也可用于判定某对象是否有如下的特殊属性:
类型 | 属性 | 描述 |
---|---|---|
module — 模块 | doc | 文档字符串 |
file | 文件名(内置模块没有文件名) | |
class — 类 | doc | 文档字符串 |
name | 类定义时所使用的名称 | |
qualname | qualified name — 限定名称 | |
module | 该类型被定义时所在的模块的名称 | |
method — 方法 | doc | 文档字符串 |
name | 该方法定义时所使用的名称 | |
qualname | qualified name — 限定名称 | |
func | 实现该方法的函数对象 | |
self | 该方法被绑定的实例,若没有绑定则为 None |
|
module | 定义此方法的模块的名称 | |
function — 函数 | doc | 文档字符串 |
name | 用于定义此函数的名称 | |
qualname | qualified name — 限定名称 | |
code | 包含已编译函数的代码对象 bytecode | |
defaults | 所有位置或关键字参数的默认值的元组 | |
kwdefaults | mapping of any default values for keyword-only parameters | |
globals | global namespace in which this function was defined | |
builtins | builtins namespace | |
annotations | mapping of parameters names to annotations; “return” key is reserved for return annotations. |
|
module | name of module in which this function was defined | |
回溯 | tbframe | 此级别的框架对象 |
tb_lasti | index of last attempted instruction in bytecode | |
tb_lineno | current line number in Python source code | |
tb_next | next inner traceback object (called by this level) | |
框架 | f_back | next outer frame object (this frame’s caller) |
f_builtins | builtins namespace seen by this frame | |
f_code | code object being executed in this frame | |
f_globals | global namespace seen by this frame | |
f_lasti | index of last attempted instruction in bytecode | |
f_lineno | current line number in Python source code | |
f_locals | local namespace seen by this frame | |
f_trace | tracing function for this frame, or None |
|
code | co_argcount | number of arguments (not including keyword only arguments, or * args) |
co_code | 原始编译字节码的字符串 | |
co_cellvars | 单元变量名称的元组(通过包含作用域引用) | |
co_consts | 字节码中使用的常量元组 | |
co_filename | 创建此代码对象的文件的名称 | |
co_firstlineno | number of first line in Python source code | |
co_flags | bitmap of CO flags, read more here |
|
co_lnotab | 编码的行号到字节码索引的映射 | |
co_freevars | tuple of names of free variables (referenced via a function’s closure) | |
co_posonlyargcount | number of positional only arguments | |
co_kwonlyargcount | number of keyword only arguments (not including * arg) | |
coname | 定义此代码对象的名称 | |
conames | 局部变量名称的元组 | |
conlocals | 局部变量的数量 | |
costacksize | 需要虚拟机堆栈空间 | |
covarnames | 参数名和局部变量的元组 | |
generator — 生成器 | name | 名称 |
qualname | qualified name — 限定名称 | |
giframe | 框架 | |
girunning | 生成器在运行吗? | |
gicode | code | |
giyieldfrom | object being iterated by yield from , or None |
|
coroutine — 协程 | name | 名称 |
_qualname | qualified name — 限定名称 | |
cr_await | object being awaited on, or None |
|
cr_frame | 框架 | |
cr_running | is the coroutine running? | |
cr_code | code | |
cr_origin | where coroutine was created, or None . See sys.set_coroutine_origin_tracking_depth() |
|
builtin | __doc | 文档字符串 |
__name | 此函数或方法的原始名称 | |
__qualname | qualified name — 限定名称 | |
__self | instance to which a method is bound, or None |
在 3.5 版更改: Add __qualname__
and gi_yieldfrom
attributes to generators.
The __name__
attribute of generators is now set from the function name, instead of the code name, and it can now be modified.
在 3.7 版更改: Add cr_origin
attribute to coroutines.
在 3.10 版更改: Add __builtins__
attribute to functions.
inspect.getmembers
(object[, predicate])
Return all the members of an object in a list of (name, value)
pairs sorted by name. If the optional predicate argument—which will be called with the value
object of each member—is supplied, only members for which the predicate returns a true value are included.
注解
getmembers()
will only return class attributes defined in the metaclass when the argument is a class and those attributes have been listed in the metaclass’ custom __dir__()
.
inspect.getmodulename
(path)
Return the name of the module named by the file path, without including the names of enclosing packages. The file extension is checked against all of the entries in importlib.machinery.all_suffixes()
. If it matches, the final path component is returned with the extension removed. Otherwise, None
is returned.
Note that this function only returns a meaningful name for actual Python modules - paths that potentially refer to Python packages will still return None
.
在 3.3 版更改: The function is based directly on importlib
.
inspect.ismodule
(object)
Return True
if the object is a module.
inspect.isclass
(object)
Return True
if the object is a class, whether built-in or created in Python code.
inspect.ismethod
(object)
Return True
if the object is a bound method written in Python.
inspect.isfunction
(object)
Return True
if the object is a Python function, which includes functions created by a lambda expression.
inspect.isgeneratorfunction
(object)
Return True
if the object is a Python generator function.
在 3.8 版更改: Functions wrapped in functools.partial()
now return True
if the wrapped function is a Python generator function.
inspect.isgenerator
(object)
Return True
if the object is a generator.
inspect.iscoroutinefunction
(object)
Return True
if the object is a coroutine function (a function defined with an async def
syntax).
3.5 新版功能.
在 3.8 版更改: Functions wrapped in functools.partial()
now return True
if the wrapped function is a coroutine function.
inspect.iscoroutine
(object)
Return True
if the object is a coroutine created by an async def
function.
3.5 新版功能.
inspect.isawaitable
(object)
Return True
if the object can be used in await
expression.
Can also be used to distinguish generator-based coroutines from regular generators:
def gen():
yield
@types.coroutine
def gen_coro():
yield
assert not isawaitable(gen())
assert isawaitable(gen_coro())
3.5 新版功能.
inspect.isasyncgenfunction
(object)
Return True
if the object is an asynchronous generator function, for example:
>>> async def agen():
... yield 1
...
>>> inspect.isasyncgenfunction(agen)
True
3.6 新版功能.
在 3.8 版更改: Functions wrapped in functools.partial()
now return True
if the wrapped function is a asynchronous generator function.
inspect.isasyncgen
(object)
Return True
if the object is an asynchronous generator iterator created by an asynchronous generator function.
3.6 新版功能.
inspect.istraceback
(object)
Return True
if the object is a traceback.
inspect.isframe
(object)
Return True
if the object is a frame.
inspect.iscode
(object)
Return True
if the object is a code.
inspect.isbuiltin
(object)
Return True
if the object is a built-in function or a bound built-in method.
inspect.isroutine
(object)
Return True
if the object is a user-defined or built-in function or method.
inspect.isabstract
(object)
Return True
if the object is an abstract base class.
inspect.ismethoddescriptor
(object)
Return True
if the object is a method descriptor, but not if ismethod()
, isclass()
, isfunction()
or isbuiltin()
are true.
This, for example, is true of int.__add__
. An object passing this test has a __get__()
method but not a __set__()
method, but beyond that the set of attributes varies. A __name__
attribute is usually sensible, and __doc__
often is.
Methods implemented via descriptors that also pass one of the other tests return False
from the ismethoddescriptor()
test, simply because the other tests promise more — you can, e.g., count on having the __func__
attribute (etc) when an object passes ismethod()
.
inspect.isdatadescriptor
(object)
Return True
if the object is a data descriptor.
Data descriptors have a __set__
or a __delete__
method. Examples are properties (defined in Python), getsets, and members. The latter two are defined in C and there are more specific tests available for those types, which is robust across Python implementations. Typically, data descriptors will also have __name__
and __doc__
attributes (properties, getsets, and members have both of these attributes), but this is not guaranteed.
inspect.isgetsetdescriptor
(object)
Return True
if the object is a getset descriptor.
CPython implementation detail: getsets are attributes defined in extension modules via PyGetSetDef
structures. For Python implementations without such types, this method will always return False
.
inspect.ismemberdescriptor
(object)
Return True
if the object is a member descriptor.
CPython implementation detail: Member descriptors are attributes defined in extension modules via PyMemberDef
structures. For Python implementations without such types, this method will always return False
.
Retrieving source code
inspect.getdoc
(object)
Get the documentation string for an object, cleaned up with cleandoc()
. If the documentation string for an object is not provided and the object is a class, a method, a property or a descriptor, retrieve the documentation string from the inheritance hierarchy.
在 3.5 版更改: Documentation strings are now inherited if not overridden.
inspect.getcomments
(object)
Return in a single string any lines of comments immediately preceding the object’s source code (for a class, function, or method), or at the top of the Python source file (if the object is a module). If the object’s source code is unavailable, return None
. This could happen if the object has been defined in C or the interactive shell.
inspect.getfile
(object)
Return the name of the (text or binary) file in which an object was defined. This will fail with a TypeError
if the object is a built-in module, class, or function.
inspect.getmodule
(object)
Try to guess which module an object was defined in.
inspect.getsourcefile
(object)
Return the name of the Python source file in which an object was defined. This will fail with a TypeError
if the object is a built-in module, class, or function.
inspect.getsourcelines
(object)
Return a list of source lines and starting line number for an object. The argument may be a module, class, method, function, traceback, frame, or code object. The source code is returned as a list of the lines corresponding to the object and the line number indicates where in the original source file the first line of code was found. An OSError
is raised if the source code cannot be retrieved.
在 3.3 版更改: OSError
is raised instead of IOError
, now an alias of the former.
inspect.getsource
(object)
Return the text of the source code for an object. The argument may be a module, class, method, function, traceback, frame, or code object. The source code is returned as a single string. An OSError
is raised if the source code cannot be retrieved.
在 3.3 版更改: OSError
is raised instead of IOError
, now an alias of the former.
inspect.cleandoc
(doc)
Clean up indentation from docstrings that are indented to line up with blocks of code.
All leading whitespace is removed from the first line. Any leading whitespace that can be uniformly removed from the second line onwards is removed. Empty lines at the beginning and end are subsequently removed. Also, all tabs are expanded to spaces.
Introspecting callables with the Signature object
3.3 新版功能.
The Signature object represents the call signature of a callable object and its return annotation. To retrieve a Signature object, use the signature()
function.
inspect.signature
(callable, **, follow_wrapped=True, globals=None, locals=None, eval_str=False*)
Return a Signature
object for the given callable
:
>>> from inspect import signature
>>> def foo(a, *, b:int, **kwargs):
... pass
>>> sig = signature(foo)
>>> str(sig)
'(a, *, b:int, **kwargs)'
>>> str(sig.parameters['b'])
'b:int'
>>> sig.parameters['b'].annotation
<class 'int'>
Accepts a wide range of Python callables, from plain functions and classes to functools.partial()
objects.
For objects defined in modules using stringized annotations (from __future__ import annotations
), signature()
will attempt to automatically un-stringize the annotations using inspect.get_annotations()
. The global
, locals
, and eval_str
parameters are passed into inspect.get_annotations()
when resolving the annotations; see the documentation for inspect.get_annotations()
for instructions on how to use these parameters.
Raises ValueError
if no signature can be provided, and TypeError
if that type of object is not supported. Also, if the annotations are stringized, and eval_str
is not false, the eval()
call(s) to un-stringize the annotations could potentially raise any kind of exception.
A slash(/) in the signature of a function denotes that the parameters prior to it are positional-only. For more info, see the FAQ entry on positional-only parameters.
3.5 新版功能: follow_wrapped
parameter. Pass False
to get a signature of callable
specifically (callable.__wrapped__
will not be used to unwrap decorated callables.)
3.10 新版功能: globals
, locals
, and eval_str
parameters.
注解
Some callables may not be introspectable in certain implementations of Python. For example, in CPython, some built-in functions defined in C provide no metadata about their arguments.
class inspect.Signature
(parameters=None, **, return_annotation=Signature.empty*)
A Signature object represents the call signature of a function and its return annotation. For each parameter accepted by the function it stores a Parameter
object in its parameters
collection.
The optional parameters argument is a sequence of Parameter
objects, which is validated to check that there are no parameters with duplicate names, and that the parameters are in the right order, i.e. positional-only first, then positional-or-keyword, and that parameters with defaults follow parameters without defaults.
The optional return_annotation argument, can be an arbitrary Python object, is the “return” annotation of the callable.
Signature objects are immutable. Use Signature.replace()
to make a modified copy.
在 3.5 版更改: Signature objects are picklable and hashable.
empty
A special class-level marker to specify absence of a return annotation.
parameters
An ordered mapping of parameters’ names to the corresponding
Parameter
objects. Parameters appear in strict definition order, including keyword-only parameters.在 3.7 版更改: Python only explicitly guaranteed that it preserved the declaration order of keyword-only parameters as of version 3.7, although in practice this order had always been preserved in Python 3.
return_annotation
The “return” annotation for the callable. If the callable has no “return” annotation, this attribute is set to
Signature.empty
.bind
(\args, *kwargs)Create a mapping from positional and keyword arguments to parameters. Returns
BoundArguments
if*args
and**kwargs
match the signature, or raises aTypeError
.bind_partial
(\args, *kwargs)Works the same way as
Signature.bind()
, but allows the omission of some required arguments (mimicsfunctools.partial()
behavior.) ReturnsBoundArguments
, or raises aTypeError
if the passed arguments do not match the signature.replace
(\, parameters*)Create a new Signature instance based on the instance replace was invoked on. It is possible to pass different
parameters
and/orreturn_annotation
to override the corresponding properties of the base signature. To remove return_annotation from the copied Signature, pass inSignature.empty
.>>> def test(a, b): ... pass >>> sig = signature(test) >>> new_sig = sig.replace(return_annotation="new return anno") >>> str(new_sig) "(a, b) -> 'new return anno'"
classmethod
from_callable
(obj, **, follow_wrapped=True, globalns=None, localns=None*)Return a
Signature
(or its subclass) object for a given callableobj
. Passfollow_wrapped=False
to get a signature ofobj
without unwrapping its__wrapped__
chain.globalns
andlocalns
will be used as the namespaces when resolving annotations.This method simplifies subclassing of
Signature
:class MySignature(Signature): pass sig = MySignature.from_callable(min) assert isinstance(sig, MySignature)
3.5 新版功能.
3.10 新版功能:
globalns
andlocalns
parameters.
class inspect.Parameter
(name, kind, **, default=Parameter.empty, annotation=Parameter.empty*)
Parameter objects are immutable. Instead of modifying a Parameter object, you can use Parameter.replace()
to create a modified copy.
在 3.5 版更改: Parameter objects are picklable and hashable.
empty
A special class-level marker to specify absence of default values and annotations.
name
The name of the parameter as a string. The name must be a valid Python identifier.
CPython implementation detail: CPython generates implicit parameter names of the form
.0
on the code objects used to implement comprehensions and generator expressions.在 3.6 版更改: These parameter names are exposed by this module as names like
implicit0
.default
The default value for the parameter. If the parameter has no default value, this attribute is set to
Parameter.empty
.annotation
The annotation for the parameter. If the parameter has no annotation, this attribute is set to
Parameter.empty
.kind
Describes how argument values are bound to the parameter. Possible values (accessible via
Parameter
, likeParameter.KEYWORD_ONLY
):名称 含意 POSITIONAL_ONLY Value must be supplied as a positional argument. Positional only parameters are those which appear before a /
entry (if present) in a Python function definition.POSITIONAL_OR_KEYWORD Value may be supplied as either a keyword or positional argument (this is the standard binding behaviour for functions implemented in Python.) VAR_POSITIONAL A tuple of positional arguments that aren’t bound to any other parameter. This corresponds to a *args*
parameter in a Python function definition.KEYWORD_ONLY Value must be supplied as a keyword argument. Keyword only parameters are those which appear after a `` or *args*
entry in a Python function definition.VAR_KEYWORD A dict of keyword arguments that aren’t bound to any other parameter. This corresponds to a *kwargs
parameter in a Python function definition.Example: print all keyword-only arguments without default values:
>>> def foo(a, b, *, c, d=10): ... pass >>> sig = signature(foo) >>> for param in sig.parameters.values(): ... if (param.kind == param.KEYWORD_ONLY and ... param.default is param.empty): ... print('Parameter:', param) Parameter: c
kind.description
Describes a enum value of Parameter.kind.
3.8 新版功能.
Example: print all descriptions of arguments:
>>> def foo(a, b, *, c, d=10): ... pass >>> sig = signature(foo) >>> for param in sig.parameters.values(): ... print(param.kind.description) positional or keyword positional or keyword keyword-only keyword-only
replace
(\, name, default*)Create a new Parameter instance based on the instance replaced was invoked on. To override a
Parameter
attribute, pass the corresponding argument. To remove a default value or/and an annotation from a Parameter, passParameter.empty
.>>> from inspect import Parameter >>> param = Parameter('foo', Parameter.KEYWORD_ONLY, default=42) >>> str(param) 'foo=42' >>> str(param.replace()) # Will create a shallow copy of 'param' 'foo=42' >>> str(param.replace(default=Parameter.empty, annotation='spam')) "foo:'spam'"
在 3.4 版更改: In Python 3.3 Parameter objects were allowed to have name
set to None
if their kind
was set to POSITIONAL_ONLY
. This is no longer permitted.
class inspect.BoundArguments
Result of a Signature.bind()
or Signature.bind_partial()
call. Holds the mapping of arguments to the function’s parameters.
arguments
A mutable mapping of parameters’ names to arguments’ values. Contains only explicitly bound arguments. Changes in
arguments
will reflect inargs
andkwargs
.Should be used in conjunction with
Signature.parameters
for any argument processing purposes.注解
Arguments for which
Signature.bind()
orSignature.bind_partial()
relied on a default value are skipped. However, if needed, useBoundArguments.apply_defaults()
to add them.在 3.9 版更改:
arguments
is now of typedict
. Formerly, it was of typecollections.OrderedDict
.args
A tuple of positional arguments values. Dynamically computed from the
arguments
attribute.kwargs
A dict of keyword arguments values. Dynamically computed from the
arguments
attribute.signature
A reference to the parent
Signature
object.apply_defaults
()Set default values for missing arguments.
For variable-positional arguments (
*args
) the default is an empty tuple.For variable-keyword arguments (
**kwargs
) the default is an empty dict.>>> def foo(a, b='ham', *args): pass >>> ba = inspect.signature(foo).bind('spam') >>> ba.apply_defaults() >>> ba.arguments {'a': 'spam', 'b': 'ham', 'args': ()}
3.5 新版功能.
The args
and kwargs
properties can be used to invoke functions:
def test(a, *, b):
...
sig = signature(test)
ba = sig.bind(10, b=20)
test(*ba.args, **ba.kwargs)
参见
PEP 362 - Function Signature Object.
The detailed specification, implementation details and examples.
类与函数
inspect.getclasstree
(classes, unique=False)
Arrange the given list of classes into a hierarchy of nested lists. Where a nested list appears, it contains classes derived from the class whose entry immediately precedes the list. Each entry is a 2-tuple containing a class and a tuple of its base classes. If the unique argument is true, exactly one entry appears in the returned structure for each class in the given list. Otherwise, classes using multiple inheritance and their descendants will appear multiple times.
inspect.getargspec
(func)
Get the names and default values of a Python function’s parameters. A named tuple ArgSpec(args, varargs, keywords, defaults)
is returned. args is a list of the parameter names. varargs and keywords are the names of the *
and **
parameters or None
. defaults is a tuple of default argument values or None
if there are no default arguments; if this tuple has n elements, they correspond to the last n elements listed in args.
3.0 版后已移除: Use getfullargspec()
for an updated API that is usually a drop-in replacement, but also correctly handles function annotations and keyword-only parameters.
Alternatively, use signature()
and Signature Object, which provide a more structured introspection API for callables.
inspect.getfullargspec
(func)
Get the names and default values of a Python function’s parameters. A named tuple is returned:
FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations)
args is a list of the positional parameter names. varargs is the name of the *
parameter or None
if arbitrary positional arguments are not accepted. varkw is the name of the **
parameter or None
if arbitrary keyword arguments are not accepted. defaults is an n-tuple of default argument values corresponding to the last n positional parameters, or None
if there are no such defaults defined. kwonlyargs is a list of keyword-only parameter names in declaration order. kwonlydefaults is a dictionary mapping parameter names from kwonlyargs to the default values used if no argument is supplied. annotations is a dictionary mapping parameter names to annotations. The special key "return"
is used to report the function return value annotation (if any).
Note that signature()
and Signature Object provide the recommended API for callable introspection, and support additional behaviours (like positional-only arguments) that are sometimes encountered in extension module APIs. This function is retained primarily for use in code that needs to maintain compatibility with the Python 2 inspect
module API.
在 3.4 版更改: This function is now based on signature()
, but still ignores __wrapped__
attributes and includes the already bound first parameter in the signature output for bound methods.
在 3.6 版更改: This method was previously documented as deprecated in favour of signature()
in Python 3.5, but that decision has been reversed in order to restore a clearly supported standard interface for single-source Python 2/3 code migrating away from the legacy getargspec()
API.
在 3.7 版更改: Python only explicitly guaranteed that it preserved the declaration order of keyword-only parameters as of version 3.7, although in practice this order had always been preserved in Python 3.
inspect.getargvalues
(frame)
Get information about arguments passed into a particular frame. A named tuple ArgInfo(args, varargs, keywords, locals)
is returned. args is a list of the argument names. varargs and keywords are the names of the *
and **
arguments or None
. locals is the locals dictionary of the given frame.
注解
This function was inadvertently marked as deprecated in Python 3.5.
inspect.formatargspec
(args[, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations[, formatarg, formatvarargs, formatvarkw, formatvalue, formatreturns, formatannotations]])
Format a pretty argument spec from the values returned by getfullargspec()
.
The first seven arguments are (args
, varargs
, varkw
, defaults
, kwonlyargs
, kwonlydefaults
, annotations
).
The other six arguments are functions that are called to turn argument names, *
argument name, **
argument name, default values, return annotation and individual annotations into strings, respectively.
例如:
>>> from inspect import formatargspec, getfullargspec
>>> def f(a: int, b: float):
... pass
...
>>> formatargspec(*getfullargspec(f))
'(a: int, b: float)'
3.5 版后已移除: Use signature()
and Signature Object, which provide a better introspecting API for callables.
inspect.formatargvalues
(args[, varargs, varkw, locals, formatarg, formatvarargs, formatvarkw, formatvalue])
Format a pretty argument spec from the four values returned by getargvalues()
. The format* arguments are the corresponding optional formatting functions that are called to turn names and values into strings.
注解
This function was inadvertently marked as deprecated in Python 3.5.
inspect.getmro
(cls)
Return a tuple of class cls’s base classes, including cls, in method resolution order. No class appears more than once in this tuple. Note that the method resolution order depends on cls’s type. Unless a very peculiar user-defined metatype is in use, cls will be the first element of the tuple.
inspect.getcallargs
(func, /, \args, *kwds)
Bind the args and kwds to the argument names of the Python function or method func, as if it was called with them. For bound methods, bind also the first argument (typically named self
) to the associated instance. A dict is returned, mapping the argument names (including the names of the *
and **
arguments, if any) to their values from args and kwds. In case of invoking func incorrectly, i.e. whenever func(*args, **kwds)
would raise an exception because of incompatible signature, an exception of the same type and the same or similar message is raised. For example:
>>> from inspect import getcallargs
>>> def f(a, b=1, *pos, **named):
... pass
>>> getcallargs(f, 1, 2, 3) == {'a': 1, 'named': {}, 'b': 2, 'pos': (3,)}
True
>>> getcallargs(f, a=2, x=4) == {'a': 2, 'named': {'x': 4}, 'b': 1, 'pos': ()}
True
>>> getcallargs(f)
Traceback (most recent call last):
...
TypeError: f() missing 1 required positional argument: 'a'
3.2 新版功能.
3.5 版后已移除: Use Signature.bind()
and Signature.bind_partial()
instead.
inspect.getclosurevars
(func)
Get the mapping of external name references in a Python function or method func to their current values. A named tuple ClosureVars(nonlocals, globals, builtins, unbound)
is returned. nonlocals maps referenced names to lexical closure variables, globals to the function’s module globals and builtins to the builtins visible from the function body. unbound is the set of names referenced in the function that could not be resolved at all given the current module globals and builtins.
TypeError
is raised if func is not a Python function or method.
3.3 新版功能.
inspect.unwrap
(func, **, stop=None*)
Get the object wrapped by func. It follows the chain of __wrapped__
attributes returning the last object in the chain.
stop is an optional callback accepting an object in the wrapper chain as its sole argument that allows the unwrapping to be terminated early if the callback returns a true value. If the callback never returns a true value, the last object in the chain is returned as usual. For example, signature()
uses this to stop unwrapping if any object in the chain has a __signature__
attribute defined.
ValueError
is raised if a cycle is encountered.
3.4 新版功能.
inspect.get_annotations
(obj, **, globals=None, locals=None, eval_str=False*)
Compute the annotations dict for an object.
obj
may be a callable, class, or module. Passing in an object of any other type raises TypeError
.
Returns a dict. get_annotations()
returns a new dict every time it’s called; calling it twice on the same object will return two different but equivalent dicts.
This function handles several details for you:
- If
eval_str
is true, values of typestr
will be un-stringized usingeval()
. This is intended for use with stringized annotations (from __future__ import annotations
). - If
obj
doesn’t have an annotations dict, returns an empty dict. (Functions and methods always have an annotations dict; classes, modules, and other types of callables may not.) - Ignores inherited annotations on classes. If a class doesn’t have its own annotations dict, returns an empty dict.
- All accesses to object members and dict values are done using
getattr()
anddict.get()
for safety. - Always, always, always returns a freshly-created dict.
eval_str
controls whether or not values of type str
are replaced with the result of calling eval()
on those values:
- If eval_str is true,
eval()
is called on values of typestr
. (Note thatget_annotations
doesn’t catch exceptions; ifeval()
raises an exception, it will unwind the stack past theget_annotations
call.) - If eval_str is false (the default), values of type
str
are unchanged.
globals
and locals
are passed in to eval()
; see the documentation for eval()
for more information. If globals
or locals
is None
, this function may replace that value with a context-specific default, contingent on type(obj)
:
- If
obj
is a module,globals
defaults toobj.__dict__
. - If
obj
is a class,globals
defaults tosys.modules[obj.__module__].__dict__
andlocals
defaults to theobj
class namespace. - If
obj
is a callable,globals
defaults toobj.__globals__
, although ifobj
is a wrapped function (usingfunctools.update_wrapper()
) it is first unwrapped.
Calling get_annotations
is best practice for accessing the annotations dict of any object. See 对象注解属性的最佳实践 for more information on annotations best practices.
3.10 新版功能.
The interpreter stack
When the following functions return “frame records,” each record is a named tuple FrameInfo(frame, filename, lineno, function, code_context, index)
. The tuple contains the frame object, the filename, the line number of the current line, the function name, a list of lines of context from the source code, and the index of the current line within that list.
在 3.5 版更改: Return a named tuple instead of a tuple.
注解
Keeping references to frame objects, as found in the first element of the frame records these functions return, can cause your program to create reference cycles. Once a reference cycle has been created, the lifespan of all objects which can be accessed from the objects which form the cycle can become much longer even if Python’s optional cycle detector is enabled. If such cycles must be created, it is important to ensure they are explicitly broken to avoid the delayed destruction of objects and increased memory consumption which occurs.
Though the cycle detector will catch these, destruction of the frames (and local variables) can be made deterministic by removing the cycle in a finally
clause. This is also important if the cycle detector was disabled when Python was compiled or using gc.disable()
. For example:
def handle_stackframe_without_leak():
frame = inspect.currentframe()
try:
# do something with the frame
finally:
del frame
If you want to keep the frame around (for example to print a traceback later), you can also break reference cycles by using the frame.clear()
method.
The optional context argument supported by most of these functions specifies the number of lines of context to return, which are centered around the current line.
inspect.getframeinfo
(frame, context=1)
Get information about a frame or traceback object. A named tuple Traceback(filename, lineno, function, code_context, index)
is returned.
inspect.getouterframes
(frame, context=1)
Get a list of frame records for a frame and all outer frames. These frames represent the calls that lead to the creation of frame. The first entry in the returned list represents frame; the last entry represents the outermost call on frame‘s stack.
在 3.5 版更改: A list of named tuples FrameInfo(frame, filename, lineno, function, code_context, index)
is returned.
inspect.getinnerframes
(traceback, context=1)
Get a list of frame records for a traceback’s frame and all inner frames. These frames represent calls made as a consequence of frame. The first entry in the list represents traceback; the last entry represents where the exception was raised.
在 3.5 版更改: A list of named tuples FrameInfo(frame, filename, lineno, function, code_context, index)
is returned.
inspect.currentframe
()
Return the frame object for the caller’s stack frame.
CPython implementation detail: This function relies on Python stack frame support in the interpreter, which isn’t guaranteed to exist in all implementations of Python. If running in an implementation without Python stack frame support this function returns None
.
inspect.stack
(context=1)
Return a list of frame records for the caller’s stack. The first entry in the returned list represents the caller; the last entry represents the outermost call on the stack.
在 3.5 版更改: A list of named tuples FrameInfo(frame, filename, lineno, function, code_context, index)
is returned.
inspect.trace
(context=1)
Return a list of frame records for the stack between the current frame and the frame in which an exception currently being handled was raised in. The first entry in the list represents the caller; the last entry represents where the exception was raised.
在 3.5 版更改: A list of named tuples FrameInfo(frame, filename, lineno, function, code_context, index)
is returned.
Fetching attributes statically
Both getattr()
and hasattr()
can trigger code execution when fetching or checking for the existence of attributes. Descriptors, like properties, will be invoked and __getattr__()
and __getattribute__()
may be called.
For cases where you want passive introspection, like documentation tools, this can be inconvenient. getattr_static()
has the same signature as getattr()
but avoids executing code when it fetches attributes.
inspect.getattr_static
(obj, attr, default=None)
Retrieve attributes without triggering dynamic lookup via the descriptor protocol, __getattr__()
or __getattribute__()
.
Note: this function may not be able to retrieve all attributes that getattr can fetch (like dynamically created attributes) and may find attributes that getattr can’t (like descriptors that raise AttributeError). It can also return descriptors objects instead of instance members.
If the instance __dict__
is shadowed by another member (for example a property) then this function will be unable to find instance members.
3.2 新版功能.
getattr_static()
does not resolve descriptors, for example slot descriptors or getset descriptors on objects implemented in C. The descriptor object is returned instead of the underlying attribute.
You can handle these with code like the following. Note that for arbitrary getset descriptors invoking these may trigger code execution:
# example code for resolving the builtin descriptor types
class _foo:
__slots__ = ['foo']
slot_descriptor = type(_foo.foo)
getset_descriptor = type(type(open(__file__)).name)
wrapper_descriptor = type(str.__dict__['__add__'])
descriptor_types = (slot_descriptor, getset_descriptor, wrapper_descriptor)
result = getattr_static(some_object, 'foo')
if type(result) in descriptor_types:
try:
result = result.__get__()
except AttributeError:
# descriptors can raise AttributeError to
# indicate there is no underlying value
# in which case the descriptor itself will
# have to do
pass
Current State of Generators and Coroutines
When implementing coroutine schedulers and for other advanced uses of generators, it is useful to determine whether a generator is currently executing, is waiting to start or resume or execution, or has already terminated. getgeneratorstate()
allows the current state of a generator to be determined easily.
inspect.getgeneratorstate
(generator)
Get current state of a generator-iterator.
- Possible states are:
- GEN_CREATED: Waiting to start execution.
- GEN_RUNNING: Currently being executed by the interpreter.
- GEN_SUSPENDED: Currently suspended at a yield expression.
- GEN_CLOSED: Execution has completed.
3.2 新版功能.
inspect.getcoroutinestate
(coroutine)
Get current state of a coroutine object. The function is intended to be used with coroutine objects created by async def
functions, but will accept any coroutine-like object that has cr_running
and cr_frame
attributes.
- Possible states are:
- CORO_CREATED: Waiting to start execution.
- CORO_RUNNING: Currently being executed by the interpreter.
- CORO_SUSPENDED: Currently suspended at an await expression.
- CORO_CLOSED: Execution has completed.
3.5 新版功能.
The current internal state of the generator can also be queried. This is mostly useful for testing purposes, to ensure that internal state is being updated as expected:
inspect.getgeneratorlocals
(generator)
Get the mapping of live local variables in generator to their current values. A dictionary is returned that maps from variable names to values. This is the equivalent of calling locals()
in the body of the generator, and all the same caveats apply.
If generator is a generator with no currently associated frame, then an empty dictionary is returned. TypeError
is raised if generator is not a Python generator object.
CPython implementation detail: This function relies on the generator exposing a Python stack frame for introspection, which isn’t guaranteed to be the case in all implementations of Python. In such cases, this function will always return an empty dictionary.
3.3 新版功能.
inspect.getcoroutinelocals
(coroutine)
This function is analogous to getgeneratorlocals()
, but works for coroutine objects created by async def
functions.
3.5 新版功能.
Code Objects Bit Flags
Python code objects have a co_flags
attribute, which is a bitmap of the following flags:
inspect.CO_OPTIMIZED
The code object is optimized, using fast locals.
inspect.CO_NEWLOCALS
If set, a new dict will be created for the frame’s f_locals
when the code object is executed.
inspect.CO_VARARGS
The code object has a variable positional parameter (*args
-like).
inspect.CO_VARKEYWORDS
The code object has a variable keyword parameter (**kwargs
-like).
inspect.CO_NESTED
The flag is set when the code object is a nested function.
inspect.CO_GENERATOR
The flag is set when the code object is a generator function, i.e. a generator object is returned when the code object is executed.
inspect.CO_NOFREE
The flag is set if there are no free or cell variables.
inspect.CO_COROUTINE
The flag is set when the code object is a coroutine function. When the code object is executed it returns a coroutine object. See PEP 492 for more details.
3.5 新版功能.
inspect.CO_ITERABLE_COROUTINE
The flag is used to transform generators into generator-based coroutines. Generator objects with this flag can be used in await
expression, and can yield from
coroutine objects. See PEP 492 for more details.
3.5 新版功能.
inspect.CO_ASYNC_GENERATOR
The flag is set when the code object is an asynchronous generator function. When the code object is executed it returns an asynchronous generator object. See PEP 525 for more details.
3.6 新版功能.
注解
The flags are specific to CPython, and may not be defined in other Python implementations. Furthermore, the flags are an implementation detail, and can be removed or deprecated in future Python releases. It’s recommended to use public APIs from the inspect
module for any introspection needs.
命令行界面
The inspect
module also provides a basic introspection capability from the command line.
By default, accepts the name of a module and prints the source of that module. A class or function within the module can be printed instead by appended a colon and the qualified name of the target object.
--details
Print information about the specified object rather than the source code
site
—— 指定域的配置钩子
源代码: Lib/site.py
这个模块将在初始化时被自动导入。 此自动导入可以通过使用解释器的 -S
选项来屏蔽。
导入此模块将会附加域特定的路径到模块搜索路径并且添加一些内建对象,除非使用了 -S
选项。 那样的话,模块可以被安全地导入,而不会对模块搜索路径和内建对象有自动的修改或添加。要明确地触发通常域特定的添加,调用函数 site.main()
。
在 3.3 版更改: 在之前即便使用了 -S
,导入此模块仍然会触发路径操纵。
It starts by constructing up to four directories from a head and a tail part. For the head part, it uses sys.prefix
and sys.exec_prefix
; empty heads are skipped. For the tail part, it uses the empty string and then lib/site-packages
(on Windows) or lib/python*X.Y*/site-packages
(on Unix and macOS). For each of the distinct head-tail combinations, it sees if it refers to an existing directory, and if so, adds it to sys.path
and also inspects the newly added path for configuration files.
在 3.5 版更改: 对 “site-python” 目录的支持已被移除。
如果名为 “pyvenv.cfg” 的文件存在于 sys.executable 之上的一个目录中,则 sys.prefix 和 sys.exec_prefix 将被设置为该目录,并且还会检查 site-packages ( sys.base_prefix 和 sys.base_exec_prefix 始终是 Python 安装的 “真实” 前缀)。 如果 “pyvenv.cfg” (引导程序配置文件)包含设置为非 “true”(不区分大小写)的 “include-system-site-packages” 键,则不会在系统级前缀中搜索 site-packages;反之则会。
一个路径配置文件是具有 *name*.pth
命名格式的文件,并且存在上面提到的四个目录之一中;它的内容是要添加到 sys.path
中的额外项目(每行一个)。不存在的项目不会添加到 sys.path
,并且不会检查项目指向的是目录还是文件。项目不会被添加到 sys.path
超过一次。空行和由 #
起始的行会被跳过。以 import
开始的行(跟着空格或 TAB)会被执行。
注解
每次启动 Python,在 .pth
文件中的可执行行都将会被运行,而不管特定的模块实际上是否需要被使用。 因此,其影响应降至最低。可执行行的主要预期目的是使相关模块可导入(加载第三方导入钩子,调整 PATH
等)。如果它发生了,任何其他的初始化都应当在模块实际导入之前完成。将代码块限制为一行是一种有意采取的措施,不鼓励在此处放置更复杂的内容。
例如,假设 sys.prefix
和 sys.exec_prefix
已经被设置为 /usr/local
。 Python X.Y 的库之后被安装为 /usr/local/lib/python*X.Y*
。假设有一个拥有三个孙目录 foo
, bar
和 spam
的子目录 /usr/local/lib/python*X.Y*/site-packages
,并且有两个路径配置文件 foot.pth
和 bar.pth
。假定 foo.pth
内容如下:
# foo package configuration
foo
bar
bletch
并且 bar.pth
包含:
# bar package configuration
bar
则下面特定版目录将以如下顺序被添加到 sys.path
。
/usr/local/lib/pythonX.Y/site-packages/bar
/usr/local/lib/pythonX.Y/site-packages/foo
请注意 bletch
已被省略因为它并不存在;bar
目前在 foo
目录之前因为 bar.pth
按字母顺序排在 foo.pth
之前;而 spam
已被省略因为它在两个路径配置文件中都未被提及。
在这些路径操作之后,会尝试导入一个名为 sitecustomize
的模块,它可以执行任意站点专属的定制。 它通常是由系统管理员在 site-packages 目录下创建的。 如此此导入失败并引发 ImportError
或其子类异常,并且异常的 name
属性等于 'sitecustomize'
,则它会被静默地忽略。 如果 Python 是在没有可用输出流的情况下启动的,例如在 Windows 上使用 pythonw.exe
(它默认被用于启动 start IDLE),则来自 sitecustomize
的输出尝试会被忽略。 任何其他异常都会导致静默且可能令人迷惑不解的进程失败。
在此之后,会尝试导入一个名为 usercustomize
的模块,它可以执行任意用户专属的定制,如果 ENABLE_USER_SITE
为真值的话。 这个文件应该在用户的 site-packages 目录中创建(见下文),该目录是 sys.path
的组成部分,除非被 -s
所禁用。 如果此导入失败并引发 ImportError
或者其子类异常,并且异常的 name
属性等于 'usercustomize'
,它会被静默地忽略。
请注意对于某些非 Unix 系统来说,sys.prefix
和 sys.exec_prefix
均为空值,并且路径操作会被跳过;但是仍然会尝试导入 sitecustomize
和 usercustomize
。
Readline 配置
在支持 readline
的系统上,这个模块也将导入并配置 rlcompleter
模块,如果 Python 是以 交互模式 启动并且不带 -S
选项的话。 默认的行为是启用 tab 键补全并使用 ~/.python_history
作为历史存档文件。 要禁用它,请删除(或重载)你的 sitecustomize
或 usercustomize
模块或 PYTHONSTARTUP
文件中的 sys.__interactivehook__
属性。
在 3.4 版更改: rlcompleter 和 history 会被自动激活。
模块内容
site.PREFIXES
site-packages 目录的前缀列表。
site.ENABLE_USER_SITE
显示用户 site-packages 目录状态的旗标。 True
意味着它被启用并被添加到 sys.path
。 False
意味着它按照用户请求被禁用 (通过 -s
或 PYTHONNOUSERSITE
)。 None
意味着它因安全理由(user 或 group id 和 effective id 之间不匹配)或是被管理员所禁用。
site.USER_SITE
Path to the user site-packages for the running Python. Can be None
if getusersitepackages()
hasn’t been called yet. Default value is ~/.local/lib/python*X.Y*/site-packages
for UNIX and non-framework macOS builds, ~/Library/Python/*X.Y*/lib/python/site-packages
for macOS framework builds, and *%APPDATA%*\Python\Python*XY*\site-packages
on Windows. This directory is a site directory, which means that .pth
files in it will be processed.
site.USER_BASE
Path to the base directory for the user site-packages. Can be None
if getuserbase()
hasn’t been called yet. Default value is ~/.local
for UNIX and macOS non-framework builds, ~/Library/Python/*X.Y*
for macOS framework builds, and *%APPDATA%*\Python
for Windows. This value is used by Distutils to compute the installation directories for scripts, data files, Python modules, etc. for the user installation scheme. See also PYTHONUSERBASE
.
site.main
()
将所有的标准站点专属目录添加到模块搜索路径。 这个函数会在导入此模块时被自动调用,除非 Python 解释器启动时附带了 -S
旗标。
在 3.3 版更改: 这个函数使用无条件调用。
site.addsitedir
(sitedir, known_paths=None)
将一个目录添加到 sys.path 并处理其 .pth
文件。 通常被用于 sitecustomize
或 usercustomize
(见下文)。
site.getsitepackages
()
返回包含所有全局 site-packages 目录的列表。
3.2 新版功能.
site.getuserbase
()
返回用户基准目录的路径 USER_BASE
。 如果它尚未被初始化,则此函数还将参照 PYTHONUSERBASE
来设置它。
3.2 新版功能.
site.getusersitepackages
()
返回用户专属 site-packages 目录的路径 USER_SITE
。 如果它尚未被初始化,则此函数还将参照 USER_BASE
来设置它。 要确定用户专属 site-packages 是否已被添加到 sys.path
则应当使用 ENABLE_USER_SITE
。
3.2 新版功能.
命令行界面
site
模块还提供了一个从命令行获取用户目录的方式:
$ python3 -m site --user-site
/home/user/.local/lib/python3.3/site-packages
如果它被不带参数地调用,它将在标准输出打印 sys.path
的内容,再打印 USER_BASE
的值以及该目录是否存在,然后打印 USER_SITE
的相应信息,最后打印 ENABLE_USER_SITE
的值。
--user-base
输出用户基本的路径。
--user-site
输出用户site-packages目录的路径。
如果同时给出了两个选项,则将打印用户基准目录和用户站点信息(总是按此顺序),并以 os.pathsep
分隔。
如果给出了其中一个选项,脚本将退出并返回以下值中的一个:如果用户级 site-packages 目录被启用则为 0
,如果它被用户禁用则为 1
,如果它因安全理由或被管理员禁用则为 2
,如果发生错误则为大于 2 的值。
参见
PEP 370 — 分用户的 site-packages 目录
自定义 Python 解释器
本章中描述的模块允许编写类似于 Python 的交互式解释器的接口。 如果你想要一个支持附加一些特殊功能到 Python 语言的 Python 解释器,你应该看看 code
模块。 ( codeop
模块是低层级的,用于支持编译可能不完整的 Python 代码块。)
本章描述的完整模块列表如下:
code
—- 解释器基类- 交互解释器对象
- 交互式控制台对象
codeop
—- 编译Python代码
code
—- 解释器基类
源代码: Lib/code.py
code
模块提供了在 Python 中实现 read-eval-print 循环的功能。它包含两个类和一些快捷功能,可用于构建提供交互式解释器的应用程序。
class code.InteractiveInterpreter
(locals=None)
这个类处理解析器和解释器状态(用户命名空间的);它不处理缓冲器、终端提示区或着输入文件名(文件名总是显示地传递)。可选的 locals 参数指定一个字典,字典里面包含将在此类执行的代码;它默认创建新的字典,其键 '__name__'
设置为 '__console__'
,键 '__doc__'
设置为 None
。
class code.InteractiveConsole
(locals=None, filename=’<console>’)
尽可能模拟交互式 Python 解释器的行为。此类建立在 InteractiveInterpreter
的基础上,使用熟悉的 sys.ps1
和 sys.ps2
作为输入提示符,并有输入缓冲。
code.interact
(banner=None, readfunc=None, local=None, exitmsg=None)
运行一个 read-eval-print 循环的便捷函数。这会创建一个新的 InteractiveConsole
实例。如果提供了 readfunc ,会设置为 InteractiveConsole.raw_input()
方法。如果提供了 local ,则将其传递给 InteractiveConsole
的构造函数,以用作解释器循环的默认命名空间。然后,如果提供了 banner 和 exitmsg ,实例的 interact()
方法会以此为标题和退出消息。控制台对象在使用后将被丢弃。
在 3.6 版更改: 加入 exitmsg 参数。
code.compile_command
(source, filename=’<input>’, symbol=’single’)
这个函数主要用来模拟 Python 解释器的主循环(即 read-eval-print 循环)。难点的部分是当用户输入不完整命令时,判断能否通过之后的输入来完成(要么成为完整的命令,要么语法错误)。该函数 几乎 和实际的解释器主循环的判断是相同的。
source 是源字符串;filename 是可选的用作读取源的文件名,默认为 '<input>'
;symbol 是可选的语法开启符号,应为 'single'
(默认), 'eval'
或 'exec'
。
如果命令完整且有效则返回一个代码对象 (等价于 compile(source, filename, symbol)
);如果命令不完整则返回 None
;如果命令完整但包含语法错误则会引发 SyntaxError
或 OverflowError
而如果命令包含无效字面值则将引发 ValueError
。
交互解释器对象
InteractiveInterpreter.runsource
(source, filename=’<input>’, symbol=’single’)
在解释器中编译并运行一段源码。 所用参数与 compile_command()
一样;filename 的默认值为 '<input>'
,symbol 则为 'single'
。 可能发生以下情况之一:
- 输入不正确;
compile_command()
引发了一个异常 (SyntaxError
或OverflowError
)。 将通过调用showsyntaxerror()
方法打印语法回溯信息。runsource()
返回False
。 - 输入不完整,需要更多输入;函数
compile_command()
返回None
。方法runsource()
返回True
。 - 输入完整;
compile_command()
返回了一个代码对象。 将通过调用runcode()
执行代码(该方法也会处理运行时异常,SystemExit
除外)。runsource()
返回False
。
该返回值用于决定使用 sys.ps1
还是 sys.ps2
来作为下一行的输入提示符。
InteractiveInterpreter.runcode
(code)
执行一个代码对象。当发生异常时,调用 showtraceback()
来显示回溯。除 SystemExit
(允许传播)以外的所有异常都会被捕获。
有关 KeyboardInterrupt
的说明,该异常可能发生于此代码的其他位置,并且并不总能被捕获。 调用者应当准备好处理它。
InteractiveInterpreter.showsyntaxerror
(filename=None)
显示刚发生的语法错误。 这不会显示堆栈回溯因为语法错误并无此种信息。 如果给出了 filename,它会被放入异常来替代 Python 解析器所提供的默认文件名,因为它在从一个字符串读取时总是会使用 '<string>'
。 输出将由 write()
方法来写入。
InteractiveInterpreter.showtraceback
()
显示刚发生的异常。 我们移除了第一个堆栈条目因为它从属于解释器对象的实现。 输出将由 write()
方法来写入。
在 3.5 版更改: 将显示完整的链式回溯,而不只是主回溯。
InteractiveInterpreter.write
(data)
将一个字符串写入到标准错误流 (sys.stderr
)。 所有派生类都应重载此方法以提供必要的正确输出处理。
交互式控制台对象
InteractiveConsole
类是 InteractiveInterpreter
的子类,因此它提供了解释器对象的所有方法,还有以下的额外方法。
InteractiveConsole.interact
(banner=None, exitmsg=None)
近似地模拟交互式 Python 终端。 可选的 banner 参数指定要在第一次交互前打印的条幅;默认情况下会类似于标准 Python 解释器所打印的内容,并附上外加圆括号的终端对象类名(这样就不会与真正的解释器混淆 —— 因为确实太像了!)
可选的 exitmsg 参数指定要在退出时打印的退出消息。 传入空字符串可以屏蔽退出消息。 如果 exitmsg 未给出或为 None
,则将打印默认消息。
在 3.4 版更改: 要禁止打印任何条幅消息,请传递一个空字符串。
在 3.6 版更改: 退出时打印退出消息。
InteractiveConsole.push
(line)
将一行源文本推入解释器。 行内容不应带有末尾换行符;它可以有内部换行符。 行内容会被添加到一个缓冲区并且会调用解释器的 runsource()
方法,附带缓冲区内容的拼接结果作为源文本。 如果显示命令已执行或不合法,缓冲区将被重置;否则,则命令尚未结束,缓冲区将在添加行后保持原样。 如果要求更多输入则返回值为 True
,如果行已按某种方式被处理则返回值为 False
(这与 runsource()
相同)。
InteractiveConsole.resetbuffer
()
从输入缓冲区中删除所有未处理的内容。
InteractiveConsole.raw_input
(prompt=’’)
输出提示并读取一行。返回的行不包含末尾的换行符。当用户输入 EOF 键序列时,会引发 EOFError
异常。默认实现是从 sys.stdin
读取;子类可以用其他实现代替。
codeop
—- 编译Python代码
源代码: Lib/codeop.py
codeop
模块提供了可以模拟Python读取-执行-打印循环的实用程序,就像在 code
模块中一样。因此,您可能不希望直接使用该模块;如果你想在程序中包含这样一个循环,你可能需要使用 code
模块。
这个任务有两个部分:
- 能够判断一行输入是否完成了一个Python语句:简而言之,告诉我们是否要打印 ‘
>>>
‘ 或 ‘...
‘。 - 记住用户已输入了哪些 future 语句,这样后续的输入可以在这些语句被启用的状态下被编译。
codeop
模块提供了分别以及同时执行这两个部分的方式。
只执行前一部分:
codeop.compile_command
(source, filename=’’, symbol=’single’)
尝试编译 source*,这应当是一个 Python 代码字符串,并且在 *source 是有效的 Python 代码时返回一个代码对象。 在此情况下,代码对象的 filename 属性将为 filename*,其默认值为 '<input>'
。 如果 *source 不是 有效的 Python 代码而是有效的 Python 代码的一个前缀时将返回 None
。
如果 source 存在问题,将引发异常。 如果存在无效的 Python 语法将引发 SyntaxError
,而如果存在无效的字面值则将引发 OverflowError
或 ValueError
。
symbol 参数确定 source 是作为一条语句 (对应默认值 'single'
),作为一系列语句 ('exec'
) 还是作为一个 expression ('eval'
) 进行编译。 任何其他值都将导致引发 ValueError
。
注解
解析器有可能(但很不常见)会在到达源码结尾之前停止解析并成功输出结果;在这种情况下,末尾的符号可能会被忽略而不是引发错误。 例如,一个反斜杠加两个换行符之后可以跟随任何无意义的符号。 一旦解析器 API 得到改进将修正这个问题。
class codeop.Compile
这个类的实例具有 __call__()
方法,其签名与内置函数 compile()
相似,区别在于如果该实例编译了包含 __future__
语句的程序文本,则实例会‘记住’并使用已生效的语句编译所有后续程序文本。
class codeop.CommandCompiler
这个类的实例具有 __call__()
方法,其签名与 compile_command()
相似;区别在于如果该实例编译了包含 __future__
语句的程序文本,则实例会‘记住’并使用已生效的语句编译编译所有后续程序文本。
导入模块
本章中介绍的模块提供了导入其他Python模块和挂钩以自定义导入过程的新方法。
本章描述的完整模块列表如下:
zipimport
—- 从 Zip 存档中导入模块- zipimporter 对象
- 例子
pkgutil
—- 包扩展工具modulefinder
—- 查找脚本使用的模块ModuleFinder
的示例用法
runpy
——查找并执行 Python 模块importlib
—-import
的实现- 概述
- 函数
importlib.abc
—— 关于导入的抽象基类importlib.resources
— 资源importlib.machinery
— Importers and path hooksimportlib.util
— Utility code for importers- 例子
- Importing programmatically
- Checking if a module can be imported
- Importing a source file directly
- Implementing lazy imports
- Setting up an importer
- Approximating
importlib.import_module()
- Using
importlib.metadata
- 概述
- 功能性 API
- Entry points
- Distribution metadata
- Distribution versions
- Distribution files
- Distribution requirements
- Package distributions
- Distributions
- Extending the search algorithm
zipimport
—- 从 Zip 存档中导入模块
源代码: Lib/zipimport.py
此模块添加了从 ZIP 格式档案中导入 Python 模块( *.py
, *.pyc
)和包的能力。通常不需要明确地使用 zipimport
模块,内置的 import
机制会自动将此模块用于 ZIP 档案路径的 sys.path
项目上。
通常, sys.path
是字符串的目录名称列表。此模块同样允许 sys.path
的一项成为命名 ZIP 文件档案的字符串。 ZIP 档案可以容纳子目录结构去支持包的导入,并且可以将归档文件中的路径指定为仅从子目录导入。比如说,路径 example.zip/lib/
将只会从档案中的 lib/
子目录导入。
任何文件都可以存在于 ZIP档案之中,但是只有 .py
和 .pyc
文件是能够导入的。不允许导入 ZIP 中的动态模组( .pyd
, .so
)。请注意,如果档案中只包含 .py
文件, Python不会尝试通过添加对应的 .pyc
文件修改档案,意思是如果 ZIP 档案不包含 .pyc
文件,导入或许会变慢。
在 3.8 版更改: 以前,不支持带有档案注释的 ZIP 档案。
参见
Phil Katz 编写的 ZIP 文件格式文档,此格式和使用的算法的创建者。
PEP 273 - 从ZIP压缩包导入模块
由 James C. Ahlstrom 编写,他也提供了实现。 Python 2.3 遵循 PEP 273 的规范,但是使用 Just van Rossum 编写的使用了 PEP 302 中描述的导入钩的实现。
importlib
- 导入机制的实现
为所有导入器的实现提供相关协议的包。
此模块定义了一个异常:
exception zipimport.ZipImportError
异常由 zipimporter 对象引发。这是 ImportError
的子类,因此,也可以捕获为 ImportError
。
zipimporter 对象
zipimporter
是用于导入 ZIP 文件的类。
class zipimport.zipimporter
(archivepath)
创建新的 zipimporter 实例。 archivepath 必须是指向 ZIP 文件的路径,或者 ZIP 文件中的特定路径。例如, foo/bar.zip/lib
的 archivepath 将在 ZIP 文件 foo/bar.zip
中的 lib
目录中查找模块(只要它存在)。
如果 archivepath 没有指向一个有效的 ZIP 档案,引发 ZipImportError
。
create_module
(spec)返回
None
来显式地请求默认语义的importlib.abc.Loader.create_module()
实现。3.10 新版功能.
exec_module
(module)importlib.abc.Loader.exec_module()
的实现。3.10 新版功能.
find_loader
(fullname, path=None)importlib.abc.PathEntryFinder.find_loader()
的实现。3.10 版后已移除: 使用
find_spec()
来代替。find_module
(fullname, path=None)搜索由 fullname 指定的模块。 fullname 必须是完全合格的(点分的)模块名。它返回 zipimporter 实例本身如果模块被找到,或者返回
None
如果没找到指定模块。可选的 path 被忽略,这是为了与导入器协议兼容。3.10 版后已移除: 使用
find_spec()
来代替。find_spec
(fullname, target=None)importlib.abc.PathEntryFinder.find_spec()
的实现。3.10 新版功能.
get_code
(fullname)返回指定模块的代码对象。 如果模块无法被导入则引发
ZipImportError
。get_data
(pathname)返回与 pathname 相关联的数据。如果不能找到文件则引发
OSError
错误。在 3.3 版更改: 曾经是
IOError
被引发而不是OSError
。get_filename
(fullname)返回如果指定模块被导入则应当要设置的
__file__
值。 如果模块无法被导入则引发ZipImportError
。3.1 新版功能.
get_source
(fullname)返回指定模块的源代码。如果没有找到模块则引发
ZipImportError
,如果档案包含模块但是没有源代码,返回None
。is_package
(fullname)如果由 fullname 指定的模块是一个包则返回
True
。如果不能找到模块则引发ZipImportError
错误。load_module
(fullname)导入由 fullname 所指定的模块。 fullname 必须为(带点号的)完整限定名称。 成功时返回导入的模块,失败时引发
ZipImportError
。3.10 版后已移除: 使用
exec_module()
来代替。invalidate_caches
()清除在 ZIP 归档文件中找到的相关文件信息的内部缓存。
3.10 新版功能.
archive
导入器关联的 ZIP 文件的文件名,没有可能的子路径。
prefix
ZIP 文件中搜索的模块的子路径。这是一个指向 ZIP 文件根目录的 zipimporter 对象的空字符串。
当与斜杠结合使用时, archive
和 prefix
属性等价于赋予 zipimporter
构造器的原始 archivepath 参数。
例子
这是一个从 ZIP 档案中导入模块的例子 - 请注意 zipimport
模块不需要明确地使用。
$ unzip -l example.zip
Archive: example.zip
Length Date Time Name
-------- ---- ---- ----
8467 11-26-02 22:30 jwzthreading.py
-------- -------
8467 1 file
$ ./python
Python 2.3 (#1, Aug 1 2003, 19:54:32)
>>> import sys
>>> sys.path.insert(0, 'example.zip') # Add .zip file to front of path
>>> import jwzthreading
>>> jwzthreading.__file__
'example.zip/jwzthreading.py'
pkgutil
—- 包扩展工具
源代码: Lib/pkgutil.py
该模块为导入系统提供了工具,尤其是在包支持方面。
class pkgutil.ModuleInfo
(module_finder, name, ispkg)
一个包含模块信息的简短摘要的命名元组。
3.6 新版功能.
pkgutil.extend_path
(path, name)
Extend the search path for the modules which comprise a package. Intended use is to place the following code in a package’s __init__.py
:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
This will add to the package’s __path__
all subdirectories of directories on sys.path
named after the package. This is useful if one wants to distribute different parts of a single logical package as multiple directories.
It also looks for *.pkg
files beginning where *
matches the name argument. This feature is similar to *.pth
files (see the site
module for more information), except that it doesn’t special-case lines starting with import
. A *.pkg
file is trusted at face value: apart from checking for duplicates, all entries found in a *.pkg
file are added to the path, regardless of whether they exist on the filesystem. (This is a feature.)
If the input path is not a list (as is the case for frozen packages) it is returned unchanged. The input path is not modified; an extended copy is returned. Items are only appended to the copy at the end.
It is assumed that sys.path
is a sequence. Items of sys.path
that are not strings referring to existing directories are ignored. Unicode items on sys.path
that cause errors when used as filenames may cause this function to raise an exception (in line with os.path.isdir()
behavior).
class pkgutil.ImpImporter
(dirname=None)
PEP 302 Finder that wraps Python’s “classic” import algorithm.
If dirname is a string, a PEP 302 finder is created that searches that directory. If dirname is None
, a PEP 302 finder is created that searches the current sys.path
, plus any modules that are frozen or built-in.
Note that ImpImporter
does not currently support being used by placement on sys.meta_path
.
3.3 版后已移除: This emulation is no longer needed, as the standard import mechanism is now fully PEP 302 compliant and available in importlib
.
class pkgutil.ImpLoader
(fullname, file, filename, etc)
Loader that wraps Python’s “classic” import algorithm.
3.3 版后已移除: This emulation is no longer needed, as the standard import mechanism is now fully PEP 302 compliant and available in importlib
.
pkgutil.find_loader
(fullname)
Retrieve a module loader for the given fullname.
This is a backwards compatibility wrapper around importlib.util.find_spec()
that converts most failures to ImportError
and only returns the loader rather than the full ModuleSpec
.
在 3.3 版更改: Updated to be based directly on importlib
rather than relying on the package internal PEP 302 import emulation.
在 3.4 版更改: Updated to be based on PEP 451
pkgutil.get_importer
(path_item)
Retrieve a finder for the given path_item.
The returned finder is cached in sys.path_importer_cache
if it was newly created by a path hook.
The cache (or part of it) can be cleared manually if a rescan of sys.path_hooks
is necessary.
在 3.3 版更改: Updated to be based directly on importlib
rather than relying on the package internal PEP 302 import emulation.
pkgutil.get_loader
(module_or_name)
Get a loader object for module_or_name.
If the module or package is accessible via the normal import mechanism, a wrapper around the relevant part of that machinery is returned. Returns None
if the module cannot be found or imported. If the named module is not already imported, its containing package (if any) is imported, in order to establish the package __path__
.
在 3.3 版更改: Updated to be based directly on importlib
rather than relying on the package internal PEP 302 import emulation.
在 3.4 版更改: Updated to be based on PEP 451
pkgutil.iter_importers
(fullname=’’)
Yield finder objects for the given module name.
If fullname contains a ‘.’, the finders will be for the package containing fullname, otherwise they will be all registered top level finders (i.e. those on both sys.meta_path and sys.path_hooks).
If the named module is in a package, that package is imported as a side effect of invoking this function.
If no module name is specified, all top level finders are produced.
在 3.3 版更改: Updated to be based directly on importlib
rather than relying on the package internal PEP 302 import emulation.
pkgutil.iter_modules
(path=None, prefix=’’)
Yields ModuleInfo
for all submodules on path, or, if path is None
, all top-level modules on sys.path
.
path should be either None
or a list of paths to look for modules in.
prefix is a string to output on the front of every module name on output.
注解
Only works for a finder which defines an iter_modules()
method. This interface is non-standard, so the module also provides implementations for importlib.machinery.FileFinder
and zipimport.zipimporter
.
在 3.3 版更改: Updated to be based directly on importlib
rather than relying on the package internal PEP 302 import emulation.
pkgutil.walk_packages
(path=None, prefix=’’, onerror=None)
Yields ModuleInfo
for all modules recursively on path, or, if path is None
, all accessible modules.
path should be either None
or a list of paths to look for modules in.
prefix is a string to output on the front of every module name on output.
Note that this function must import all packages (not all modules!) on the given path, in order to access the __path__
attribute to find submodules.
onerror is a function which gets called with one argument (the name of the package which was being imported) if any exception occurs while trying to import a package. If no onerror function is supplied, ImportError
s are caught and ignored, while all other exceptions are propagated, terminating the search.
示例:
# list all modules python can access
walk_packages()
# list all submodules of ctypes
walk_packages(ctypes.__path__, ctypes.__name__ + '.')
注解
Only works for a finder which defines an iter_modules()
method. This interface is non-standard, so the module also provides implementations for importlib.machinery.FileFinder
and zipimport.zipimporter
.
在 3.3 版更改: Updated to be based directly on importlib
rather than relying on the package internal PEP 302 import emulation.
pkgutil.get_data
(package, resource)
从包中获取一个资源。
This is a wrapper for the loader get_data
API. The package argument should be the name of a package, in standard module format (foo.bar
). The resource argument should be in the form of a relative filename, using /
as the path separator. The parent directory name ..
is not allowed, and nor is a rooted name (starting with a /
).
The function returns a binary string that is the contents of the specified resource.
For packages located in the filesystem, which have already been imported, this is the rough equivalent of:
d = os.path.dirname(sys.modules[package].__file__)
data = open(os.path.join(d, resource), 'rb').read()
If the package cannot be located or loaded, or it uses a loader which does not support get_data
, then None
is returned. In particular, the loader for namespace packages does not support get_data
.
pkgutil.resolve_name
(name)
Resolve a name to an object.
This functionality is used in numerous places in the standard library (see bpo-12915) - and equivalent functionality is also in widely used third-party packages such as setuptools, Django and Pyramid.
It is expected that name will be a string in one of the following formats, where W is shorthand for a valid Python identifier and dot stands for a literal period in these pseudo-regexes:
W(.W)*
W(.W)*:(W(.W)*)?
The first form is intended for backward compatibility only. It assumes that some part of the dotted name is a package, and the rest is an object somewhere within that package, possibly nested inside other objects. Because the place where the package stops and the object hierarchy starts can’t be inferred by inspection, repeated attempts to import must be done with this form.
In the second form, the caller makes the division point clear through the provision of a single colon: the dotted name to the left of the colon is a package to be imported, and the dotted name to the right is the object hierarchy within that package. Only one import is needed in this form. If it ends with the colon, then a module object is returned.
The function will return an object (which might be a module), or raise one of the following exceptions:
ValueError
— if name isn’t in a recognised format.
ImportError
— if an import failed when it shouldn’t have.
AttributeError
— If a failure occurred when traversing the object hierarchy within the imported package to get to the desired object.
3.9 新版功能.
modulefinder
—- 查找脚本使用的模块
该模块提供了一个 ModuleFinder
类,可用于确定脚本导入的模块集。 modulefinder.py
也可以作为脚本运行,给出 Python 脚本的文件名作为参数,之后将打印导入模块的报告。
modulefinder.AddPackagePath
(pkg_name, path)
记录名为 pkg_name 的包可以在指定的 path 中找到。
modulefinder.ReplacePackage
(oldname, newname)
允许指定名为 oldname 的模块实际上是名为 newname 的包。
class modulefinder.ModuleFinder
(path=None, debug=0, excludes=[], replace_paths=[])
该类提供 run_script()
和 report()
方法,用于确定脚本导入的模块集。 path 可以是搜索模块的目录列表;如果没有指定,则使用 sys.path
。 debug 设置调试级别;更高的值使类打印调试消息,关于它正在做什么。 excludes 是要从分析中排除的模块名称列表。 replace_paths 是将在模块路径中替换的 (oldpath, newpath)
元组的列表。
report
()将报告打印到标准输出,列出脚本导入的模块及其路径,以及缺少或似乎缺失的模块。
run_script
(pathname)分析 pathname 文件的内容,该文件必须包含 Python 代码。
modules
一个将模块名称映射到模块的字典。
ModuleFinder
的示例用法
稍后将分析的脚本(bacon.py):
import re, itertools
try:
import baconhameggs
except ImportError:
pass
try:
import guido.python.ham
except ImportError:
pass
将输出 bacon.py 报告的脚本:
from modulefinder import ModuleFinder
finder = ModuleFinder()
finder.run_script('bacon.py')
print('Loaded modules:')
for name, mod in finder.modules.items():
print('%s: ' % name, end='')
print(','.join(list(mod.globalnames.keys())[:3]))
print('-'*50)
print('Modules not imported:')
print('\n'.join(finder.badmodules.keys()))
输出样例(可能因架构而异):
Loaded modules:
_types:
copyreg: _inverted_registry,_slotnames,__all__
sre_compile: isstring,_sre,_optimize_unicode
_sre:
sre_constants: REPEAT_ONE,makedict,AT_END_LINE
sys:
re: __module__,finditer,_expand
itertools:
__main__: re,itertools,baconhameggs
sre_parse: _PATTERNENDERS,SRE_FLAG_UNICODE
array:
types: __module__,IntType,TypeType
---------------------------------------------------
Modules not imported:
guido.python.ham
baconhameggs
runpy
——查找并执行 Python 模块
源代码: Lib/runpy.py
runpy
模块用于找到并运行 Python 的模块,而无需首先导入。主要用于实现 -m
命令行开关,以允许用 Python 模块命名空间而不是文件系统来定位脚本。
请注意,这 并非 一个沙盒模块——所有代码都在当前进程中运行,所有副作用(如其他模块对导入操作进行了缓存)在函数返回后都会留存。
此外,在 runpy
函数返回后,任何由已执行代码定义的函数和类都不能保证正确工作。如果某使用场景不能接收此限制,那么选用 importlib
可能更合适些。
runpy
模块提供两个函数:
runpy.run_module
(mod_name, init_globals=None, run_name=None, alter_sys=False)
执行给定模块的代码,并返回结果模块的 globals 字典。 该模块的代码首先会用标准的导入机制去查找定位 (详情请参阅 PEP 302),然后在全新的模块命名空间中运行。
参数 mod_name 应该是一个绝对模块名。如果模块名指向一个包,而不是普通的模块,那么该包会被导入,然后执行包中的 __main__
子模块,并返回结果模块的 globals 字典。
可选的字典参数 init_globals 可用来在代码执行前预填充模块的 globals 字典。给出的字典参数不会被修改。如果字典中定义了以下任意一个特殊全局变量,这些定义都会被 run_module()
覆盖。
The special global variables __name__
, __spec__
, __file__
, __cached__
, __loader__
and __package__
are set in the globals dictionary before the module code is executed (Note that this is a minimal set of variables - other variables may be set implicitly as an interpreter implementation detail).
若可选参数 __name__
不为 None
则设为 run_name*,若此名称的模块是一个包则设为 mod_name + '.__main__'
,否则设为 *mod_name 参数。
__spec__
将设为合适的 实际 导入模块(也就是说,__spec__.name
一定是 mod_name 或 mod_name + '.__main__
,而不是 run_name)。
__file__
、__cached__
、 __loader__
和 __package__
根据模块规格进行 常规设置
如果给出了参数 alter_sys 并且值为 True
,那么 sys.argv[0]
将被更新为 __file__
的值,sys.modules[__name__]
将被更新为临时模块对象。在函数返回前, sys.argv[0]
和 sys.modules[__name__]
将会复原。
注意,这种对 sys
的操作不是线程安全的。其他线程可能会看到初始化不完整的模块,以及变动后的参数列表。如果从线程中的代码调用此函数,建议单实例运行 sys
模块。
参见
-m
选项由命令行提供相同功能。
在 3.1 版更改: 加入了 查找 __main__
子模块并执行软件包的能力。
在 3.2 版更改: 加入了 __cached__
全局变量(参见 PEP 3147 )。
在 3.4 版更改: 充分利用 PEP 451 加入的模块规格功能。使得以这种方式运行的模块能够正确设置 __cached__
,并确保真正的模块名称总是可以通过 __spec__.name
的形式访问。
runpy.run_path
(file_path, init_globals=None, run_name=None)
执行指定位置的代码,并返回结果模块的 globals 字典。与提供给 CPython 命令行的脚本名称一样,给出的路径可以指向 Python 源文件、编译过的字节码文件或包含__main__
模块的有效 sys.path 项(例如一个包含顶级__main__.py
文件的 zip 文件)。
对于直接的脚本而言,指定代码将直接在一个新的模块命名空间中运行。对于一个有效的 sys.path 项(通常是一个 zip 文件或目录),其首先会被添加到 sys.path
的开头。然后,本函数用更新后的路径查找并执行 __main__
模块。请注意,即便在指定位置不存在主模块,也没有特别的保护措施来防止调用存在于 sys.path
其他地方的 __main__
。
利用可选的字典参数 init_globals ,可在代码执行前预填模块的 globals 字典。给出的字典参数不会被修改。如果给出的字典中定义了下列特殊全局变量,这些定义均会被 run_module()
覆盖。
The special global variables __name__
, __spec__
, __file__
, __cached__
, __loader__
and __package__
are set in the globals dictionary before the module code is executed (Note that this is a minimal set of variables - other variables may be set implicitly as an interpreter implementation detail).
如果该可选参数不为 None
,则 __name__
被设为 run_name,否则为 '<run_path>'
。
如果提供的路径直接引用了一个脚本文件(无论是源码文件还是预编译的字节码),那么 __file__
将设为给出的路径,而 __spec__
、__cached__
、__loader__
和 __package__
都将设为 None
。
如果给出的路径是对有效 sys.path 项的引用,那么 __spec__
将为导入的 __main__
模块进行正确设置 (也就是说,__spec__.name
将一定是 __main__
)。 __file__
, __cached__
, __loader__
和 __package__
将依据模块规格 进行常规设置。
sys
模块也做了一些改动。 首先,如上所述,sys.path
可能会被修改。 sys.argv[0]
被更新为 file_path
的值,sys.modules[__name__]
被更新为正在被执行的模块的临时模块对象。 在函数返回之前,对 sys
中条目的所有修改都会被复原。
注意,与 run_module()
不同的是,本函数对 sys
的修改不是可有可无的,因为这些调整对于 sys.path 项能够顺利执行至关重要。由于依然存在线程安全的限制,在线程代码中使用本函数时应采用导入锁进行序列运行,或者委托给一个单独的进程。
参见
接口选项 用于在命令行上实现同等功能(python path/to/script
)。
3.2 新版功能.
在 3.4 版更改: 已作更新,以便充分利用 PEP 451 加入的模块规格功能。使得从有效 sys.path 项导入__main__
而不是直接执行的情况下,能够正确设置 __cached__
。
参见
PEP 338 — 将模块作为脚本执行
PEP 由 Nick Coghlan 撰写并实现。
PEP 366 ——主模块的显式相对导入
PEP 由 Nick Coghlan 撰写并实现。
PEP 451 —— 导入系统采用的 ModuleSpec 类型
PEP 由 Eric Snow 撰写并实现。
命令行与环境 —— CPython 命令行详解
importlib.import_module()
函数
importlib
—- import
的实现
3.1 新版功能.
概述
importlib
包的目的有两个。 第一个目的是在 Python 源代码中提供 import
语句的实现(并且因此而扩展 __import__()
函数)。 这提供了一个可移植到任何 Python 解释器的 import
实现。 相比使用 Python 以外的编程语言实现方式,这一实现更加易于理解。
第二个目的是实现 import
的部分被公开在这个包中,使得用户更容易创建他们自己的自定义对象 (通常被称为 importer) 来参与到导入过程中。
参见
import 语句
import
语句的语言参考
包规格说明
包的初始规范。自从编写这个文档开始,一些语义已经发生改变了(比如基于 sys.modules
中 None
的重定向)。
__import__()
函数
import
语句是这个函数的语法糖。
在忽略大小写的平台上进行导入
定义 Python 源代码编码
新导入钩子
导入:多行和绝对/相对
主模块显式相对导入
隐式命名空间包
导入系统的一个模块规范类型
消除PYO文件
多阶段扩展模块初始化
确定性的 pyc 文件
使用 UTF-8 作为默认的源编码
PYC 仓库目录
函数
importlib.__import__
(name, globals=None, locals=None, fromlist=(), level=0)
内置 __import__()
函数的实现。
注解
程序式地导入模块应该使用 import_module()
而不是这个函数。
importlib.import_module
(name, package=None)
导入一个模块。参数 name 指定了以绝对或相对导入方式导入什么模块 (比如要么像这样 pkg.mod
或者这样 ..mod
)。如果参数 name 使用相对导入的方式来指定,那么那个参数 packages 必须设置为那个包名,这个包名作为解析这个包名的锚点 (比如 import_module('..mod', 'pkg.subpkg')
将会导入 pkg.mod
)。
import_module()
函数是一个对 importlib.__import__()
进行简化的包装器。 这意味着该函数的所有主义都来自于 importlib.__import__()
。 这两个函数之间最重要的不同点在于 import_module()
返回指定的包或模块 (例如 pkg.mod
),而 __import__()
返回最高层级的包或模块 (例如 pkg
)。
如果动态导入一个自从解释器开始执行以来被创建的模块(即创建了一个 Python 源代码文件),为了让导入系统知道这个新模块,可能需要调用 invalidate_caches()
。
在 3.3 版更改: 父包会被自动导入。
importlib.find_loader
(name, path=None)
查找一个模块的加载器,可选择地在指定的 path 里面。如果这个模块是在 sys.modules
,那么返回 sys.modules[name].__loader__
(除非这个加载器是 None
或者是没有被设置, 在这样的情况下,会引起 ValueError
异常)。 否则使用 sys.meta_path
的一次搜索就结束。如果未发现加载器,则返回 None
。
点状的名称没有使得它父包或模块隐式地导入,因为它需要加载它们并且可能不需要。为了适当地导入一个子模块,需要导入子模块的所有父包并且使用正确的参数提供给 path。
3.3 新版功能.
在 3.4 版更改: 如果没有设置 __loader__
,会引起 ValueError
异常,就像属性设置为 None
的时候一样。
3.4 版后已移除: 使用 importlib.util.find_spec()
来代替。
importlib.invalidate_caches
()
使查找器存储在 sys.meta_path
中的内部缓存无效。如果一个查找器实现了 invalidate_caches()
,那么它会被调用来执行那个无效过程。 如果创建/安装任何模块,同时正在运行的程序是为了保证所有的查找器知道新模块的存在,那么应该调用这个函数。
3.3 新版功能.
importlib.reload
(module)
重新加载之前导入的 module。那个参数必须是一个模块对象,所以它之前必须已经成功导入了。这样做是有用的,如果使用外部编辑器编已经辑过了那个模块的源代码文件并且想在退出 Python 解释器之前试验这个新版本的模块。函数的返回值是那个模块对象(如果重新导入导致一个不同的对象放置在 sys.modules
中,那么那个模块对象是有可能会不同)。
当执行 reload()
的时候:
- Python 模块的代码会被重新编译并且那个模块级的代码被重新执行,通过重新使用一开始加载那个模块的 loader,定义一个新的绑定在那个模块字典中的名称的对象集合。扩展模块的
init
函数不会被调用第二次。 - 与Python中的所有的其它对象一样,旧的对象只有在它们的引用计数为0之后才会被回收。
- 模块命名空间中的名称重新指向任何新的或更改后的对象。
- 其他旧对象的引用(例如那个模块的外部名称)不会被重新绑定到引用的新对象的,并且如果有需要,必须在出现的每个命名空间中进行更新。
有一些其他注意事项:
当一个模块被重新加载的时候,它的字典(包含了那个模块的全区变量)会被保留。名称的重新定义会覆盖旧的定义,所以通常来说这不是问题。如果一个新模块没有定义在旧版本模块中定义的名称,则将保留旧版本中的定义。这一特性可用于作为那个模块的优点,如果它维护一个全局表或者对象的缓存 —— 使用 try
语句,就可以测试表的存在并且跳过它的初始化,如果有需要的话:
try:
cache
except NameError:
cache = {}
重新加载内置的或者动态加载模块,通常来说不是很有用处。不推荐重新加载”sys
,__main__
,builtins
和其它关键模块。在很多例子中,扩展模块并不是设计为不止一次的初始化,并且当重新加载时,可能会以任意方式失败。
如果一个模块使用 from
… import
… 导入的对象来自另外一个模块,给其它模块调用 reload()
不会重新定义来自这个模块的对象 —— 解决这个问题的一种方式是重新执行 from
语句,另一种方式是使用 import
和限定名称(module.name)来代替。
如果一个模块创建一个类的实例,重新加载定义那个类的模块不影响那些实例的方法定义———它们继续使用旧类中的定义。对于子类来说同样是正确的。
3.4 新版功能.
在 3.7 版更改: ModuleNotFoundError
is raised when the module being reloaded lacks a ModuleSpec
.
importlib.abc
—— 关于导入的抽象基类
源代码: Lib/importlib/abc.py
The importlib.abc
module contains all of the core abstract base classes used by import
. Some subclasses of the core abstract base classes are also provided to help in implementing the core ABCs.
ABC 类的层次结构:
object
+-- Finder (deprecated)
| +-- MetaPathFinder
| +-- PathEntryFinder
+-- Loader
+-- ResourceLoader --------+
+-- InspectLoader |
+-- ExecutionLoader --+
+-- FileLoader
+-- SourceLoader
class importlib.abc.Finder
代表 finder 的一个抽象基类
3.3 版后已移除: 使用 MetaPathFinder
或 PathEntryFinder
来代替。
abstractmethod
find_module
(fullname, path=None)为指定的模块查找 loader 定义的抽象方法。本来是在 PEP 302 指定的,这个方法是在
sys.meta_path
和基于路径的导入子系统中使用。在 3.4 版更改: 当被调用的时候,返回
None
而不是引发NotImplementedError
。3.10 版后已移除: Implement
MetaPathFinder.find_spec()
orPathEntryFinder.find_spec()
instead.
class importlib.abc.MetaPathFinder
代表 meta path finder 的一个抽象基类。 为了保持兼容性,这是 Finder
的一个子类。
3.3 新版功能.
在 3.10 版更改: No longer a subclass of Finder
.
find_spec
(fullname, path, target=None)An abstract method for finding a spec for the specified module. If this is a top-level import, path will be
None
. Otherwise, this is a search for a subpackage or module and path will be the value of__path__
from the parent package. If a spec cannot be found,None
is returned. When passed in,target
is a module object that the finder may use to make a more educated guess about what spec to return.importlib.util.spec_from_loader()
may be useful for implementing concreteMetaPathFinders
.3.4 新版功能.
find_module
(fullname, path)一个用于查找指定的模块中 loader 的遗留方法。如果这是最高层级的导入,path 的值将会是
None
。否则,这是一个查找子包或者模块的方法,并且 path 的值将会是来自父包的__path__
的值。如果未发现加载器,返回None
。如果定义了
find_spec()
方法,则提供了向后兼容的功能。在 3.4 版更改: 当调用这个方法的时候返回
None
而不是引发NotImplementedError
。 可以使用find_spec()
来提供功能。3.4 版后已移除: 使用
find_spec()
来代替。invalidate_caches
()当被调用的时候,一个可选的方法应该将查找器使用的任何内部缓存进行无效。将在
sys.meta_path
上的所有查找器的缓存进行无效的时候,这个函数被importlib.invalidate_caches()
所使用。在 3.4 版更改: 当方法被调用的时候,方法返回是
None
而不是NotImplemented
。
class importlib.abc.PathEntryFinder
An abstract base class representing a path entry finder. Though it bears some similarities to MetaPathFinder
, PathEntryFinder
is meant for use only within the path-based import subsystem provided by importlib.machinery.PathFinder
.
3.3 新版功能.
在 3.10 版更改: No longer a subclass of Finder
.
find_spec
(fullname, target=None)An abstract method for finding a spec for the specified module. The finder will search for the module only within the path entry to which it is assigned. If a spec cannot be found,
None
is returned. When passed in,target
is a module object that the finder may use to make a more educated guess about what spec to return.importlib.util.spec_from_loader()
may be useful for implementing concretePathEntryFinders
.3.4 新版功能.
find_loader
(fullname)一个用于在模块中查找一个 loader 的遗留方法。 返回一个
(loader, portion)
的2元组,portion
是一个贡献给命名空间包部分的文件系统位置的序列。 加载器可能是None
,同时正在指定的portion
表示的是贡献给命名空间包的文件系统位置。portion
可以使用一个空列表来表示加载器不是命名空间包的一部分。 如果loader
是None
并且portion
是一个空列表,那么命名空间包中无加载器或者文件系统位置可查找到(即在那个模块中未能找到任何东西)。如果定义了
find_spec()
,则提供了向后兼容的功能。在 3.4 版更改: 返回
(None, [])
而不是引发NotImplementedError
。 当可于提供相应的功能的时候,使用find_spec()
。3.4 版后已移除: 使用
find_spec()
来代替。find_module
(fullname)Finder.find_module
的具体实现,该方法等价于``self.find_loader(fullname)[0]()
。3.4 版后已移除: 使用
find_spec()
来代替。invalidate_caches
()An optional method which, when called, should invalidate any internal cache used by the finder. Used by
importlib.machinery.PathFinder.invalidate_caches()
when invalidating the caches of all cached finders.
class importlib.abc.Loader
loader 的抽象基类。 关于一个加载器的实际定义请查看 PEP 302。
加载器想要支持资源读取应该实现一个由 importlib.abc.ResourceReader
指定的get_resource_reader(fullname)
方法。
在 3.7 版更改: 引入了可选的 get_resource_reader()
方法。
create_module
(spec)当导入一个模块的时候,一个返回将要使用的那个模块对象的方法。这个方法可能返回
None
,这暗示着应该发生默认的模块创建语义。”3.4 新版功能.
在 3.5 版更改: 从 Python 3.6 开始,当定义了
exec_module()
的时候,这个方法将不会是可选的。exec_module
(module)当一个模块被导入或重新加载时,一个抽象方法在它自己的命名空间中执行那个模块。当调用
exec_module()
的时候,那个模块应该已经被初始化 了。当这个方法存在时,必须定义create_module()
。3.4 新版功能.
在 3.6 版更改:
create_module()
也必须被定义。load_module
(fullname)用于加载一个模块的传统方法。如果这个模块不能被导入,将引起
ImportError
异常,否则返回那个被加载的模块。如果请求的模块已经存在
sys.modules
,应该使用并且重新加载那个模块。 否则加载器应该是创建一个新的模块并且在任何家过程开始之前将这个新模块插入到sys.modules
中,来阻止递归导入。 如果加载器插入了一个模块并且加载失败了,加载器必须从sys.modules
中将这个模块移除。在加载器开始执行之前,已经在sys.modules
中的模块应该被忽略 (查看importlib.util.module_for_loader()
)。加载器应该在模块上面设置几个属性。(要知道当重新加载一个模块的时候,那些属性某部分可以改变):
__name__
模块的名字
- [`__file__`]($e6a440f13a5f432a.md#file__ "__file__")
模块数据存储的路径(不是为了内置的模块而设置)
- [`__cached__`]($e6a440f13a5f432a.md#cached__ "__cached__")
被存储或应该被存储的模块的编译版本的路径(当这个属性不恰当的时候不设置)。
- [`__path__`]($e6a440f13a5f432a.md#path__ "__path__")
指定在一个包中搜索路径的一个字符串列表。这个属性不在模块上面进行设置。
- [`__package__`]($e6a440f13a5f432a.md#package__ "__package__")
The fully-qualified name of the package under which the module was loaded as a submodule (or the empty string for top-level modules). For packages, it is the same as [`__name__`]($e6a440f13a5f432a.md#name__ "__name__"). The [`importlib.util.module_for_loader()`](#importlib.util.module_for_loader "importlib.util.module_for_loader") decorator can handle the details for [`__package__`]($e6a440f13a5f432a.md#package__ "__package__").
- [`__loader__`]($e6a440f13a5f432a.md#loader__ "__loader__")
用来加载那个模块的加载器。 [`importlib.util.module_for_loader()`](#importlib.util.module_for_loader "importlib.util.module_for_loader") 装饰器可以处理 [`__package__`]($e6a440f13a5f432a.md#package__ "__package__") 的细节。
当 [`exec_module()`](#importlib.abc.Loader.exec_module "importlib.abc.Loader.exec_module") 可用的时候,那么则提供了向后兼容的功能。
在 3.4 版更改: 当这个方法被调用的时候,触发 [`ImportError`]($177bd954d1cc6696.md#ImportError "ImportError") 异常而不是 [`NotImplementedError`]($177bd954d1cc6696.md#NotImplementedError "NotImplementedError")。当 [`exec_module()`](#importlib.abc.Loader.exec_module "importlib.abc.Loader.exec_module") 可用的时候,使用它的功能。
3.4 版后已移除: 加载模块推荐的使用的 API 是 [`exec_module()`](#importlib.abc.Loader.exec_module "importlib.abc.Loader.exec_module") (和 [`create_module()`](#importlib.abc.Loader.create_module "importlib.abc.Loader.create_module"))。 加载器应该实现它而不是 load\_module()。 当 exec\_module() 被实现的时候,导入机制关心的是 load\_module() 所有其他的责任。
module_repr
(module)一个遗留方法,在实现时计算并返回给定模块的 repr,作为字符串。 模块类型的默认 repr() 将根据需要使用此方法的结果。
3.3 新版功能.
在 3.4 版更改: 是可选的方法而不是一个抽象方法。
3.4 版后已移除: 现在导入机制会自动地关注这个方法。
class importlib.abc.ResourceReader
Superseded by TraversableResources
提供读取 resources 能力的一个 abstract base class 。
从这个 ABC 的视角出发,resource 指一个包附带的二进制文件。常见的如在包的 __init__.py
文件旁的数据文件。这个类存在的目的是为了将对数据文件的访问进行抽象,这样包就和其数据文件的存储方式无关了。不论这些文件是存放在一个 zip 文件里还是直接在文件系统内。
对于该类中的任一方法,resource 参数的值都需要是一个在概念上表示文件名称的 path-like object。 这意味着任何子目录的路径都不该出现在 resouce 参数值内。 因为对于阅读器而言,包的位置就代表着「目录」。 因此目录和文件名就分别对应于包和资源。 这也是该类的实例都需要和一个包直接关联(而不是潜在指代很多包或者一整个模块)的原因。
想支持资源读取的加载器需要提供一个返回实现了此 ABC 的接口的 get_resource_reader(fullname)
方法。如果通过全名指定的模块不是一个包,这个方法应该返回 None
。 当指定的模块是一个包时,应该只返回一个与这个抽象类ABC兼容的对象。
3.7 新版功能.
abstractmethod
open_resource
(resource)返回一个打开的 file-like object 用于 resource 的二进制读取。
如果无法找到资源,将会引发
FileNotFoundError
。abstractmethod
resource_path
(resource)返回 resource 的文件系统路径。
如果资源并不实际存在于文件系统中,将会引发
FileNotFoundError
。abstractmethod
is_resource
(name)如果name 被视作资源,则返回True。如果name不存在,则引发
FileNotFoundError
异常。abstractmethod
contents
()反回由字符串组成的 iterable,表示这个包的所有内容。 请注意并不要求迭代器返回的所有名称都是实际的资源,例如返回
is_resource()
为假值的名称也是可接受的。允许非资源名字被返回是为了允许存储的一个包和它的资源的方式是已知先验的并且非资源名字会有用的情况。比如,允许返回子目录名字,目的是当得知包和资源存储在文件系统上面的时候,能够直接使用子目录的名字。
这个抽象方法返回了一个不包含任何内容的可迭代对象。
class importlib.abc.ResourceLoader
一个 loader 的抽象基类,它实现了可选的 PEP 302 协议用于从存储后端加载任意资源。
3.7 版后已移除: 由于要支持使用 importlib.abc.ResourceReader
类来加载资源,这个 ABC 已经被弃用了。
abstractmethod
get_data
(path)一个用于返回位于 path 的字节数据的抽象方法。有一个允许存储任意数据的类文件存储后端的加载器能够实现这个抽象方法来直接访问这些被存储的数据。如果不能够找到 path,则会引发
OSError
异常。path 被希望使用一个模块的__file
属性或来自一个包的__path__
来构建。在 3.4 版更改: 引发
OSError
异常而不是NotImplementedError
异常。
class importlib.abc.InspectLoader
一个实现加载器检查模块可选的 PEP 302 协议的 loader 的抽象基类。
get_code
(fullname)返回一个模块的代码对象,或如果模块没有一个代码对象(例如,对于内置的模块来说,这会是这种情况),则为
None
。 如果加载器不能找到请求的模块,则引发ImportError
异常。注解
当这个方法有一个默认的实现的时候,出于性能方面的考虑,如果有可能的话,建议覆盖它。
在 3.4 版更改: 不再抽象并且提供一个具体的实现。
abstractmethod
get_source
(fullname)一个返回模块源的抽象方法。使用 universal newlines 作为文本字符串被返回,将所有可识别行分割符翻译成
'\n'
字符。 如果没有可用的源(例如,一个内置模块),则返回None
。 如果加载器不能找到指定的模块,则引发ImportError
异常。在 3.4 版更改: 引发
ImportError
而不是NotImplementedError
。is_package
(fullname)An optional method to return a true value if the module is a package, a false value otherwise.
ImportError
is raised if the loader cannot find the module.在 3.4 版更改: 引发
ImportError
而不是NotImplementedError
。static
source_to_code
(data, path=’<string>’)创建一个来自Python源码的代码对象。
参数 data 可以是任意
compile()
函数支持的类型(例如字符串或字节串)。 参数 path 应该是源代码来源的路径,这可能是一个抽象概念(例如位于一个 zip 文件中)。在有后续代码对象的情况下,可以在一个模块中通过运行
exec(code, module.__dict__)
来执行它。3.4 新版功能.
在 3.5 版更改: 使得这个方法变成静态的。
exec_module
(module)Loader.exec_module()
的实现。3.4 新版功能.
load_module
(fullname)Loader.load_module()
的实现。3.4 版后已移除: 使用
exec_module()
来代替。
class importlib.abc.ExecutionLoader
一个继承自 InspectLoader
的抽象基类,当被实现时,帮助一个模块作为脚本来执行。 这个抽象基类表示可选的 PEP 302 协议。
abstractmethod
get_filename
(fullname)一个用来为指定模块返回
__file__
的值的抽象方法。如果无路径可用,则引发ImportError
。如果源代码可用,那么这个方法返回源文件的路径,不管是否是用来加载模块的字节码。
在 3.4 版更改: 引发
ImportError
而不是NotImplementedError
。
class importlib.abc.FileLoader
(fullname, path)
一个继承自 ResourceLoader
和 ExecutionLoader
,提供 ResourceLoader.get_data()
和 ExecutionLoader.get_filename()
具体实现的抽象基类。
参数fullname是加载器要处理的模块的完全解析的名字。参数path是模块文件的路径。
3.3 新版功能.
name
加载器可以处理的模块的名字。
path
模块的文件路径
load_module
(fullname)调用super的
load_module()
。3.4 版后已移除: 使用
Loader.exec_module()
来代替。abstractmethod
get_filename
(fullname)返回
path
。abstractmethod
get_data
(path)读取 path 作为二进制文件并且返回来自它的字节数据。
class importlib.abc.SourceLoader
一个用于实现源文件(和可选地字节码)加载的抽象基类。这个类继承自 ResourceLoader
和 ExecutionLoader
,需要实现:
ResourceLoader.get_data()
ExecutionLoader.get_filename()
应该是只返回源文件的路径;不支持无源加载。
由这个类定义的抽象方法用来添加可选的字节码文件支持。不实现这些可选的方法(或导致它们引发 NotImplementedError
异常)导致这个加载器只能与源代码一起工作。 实现这些方法允许加载器能与源 和 字节码文件一起工作。不允许只提供字节码的 无源式 加载。字节码文件是通过移除 Python 编译器的解析步骤来加速加载的优化,并且因此没有开放出字节码专用的 API。
path_stats
(path)返回一个包含关于指定路径的元数据的
dict
的可选的抽象方法。 支持的字典键有:'mtime'
(必选项): 一个表示源码修改时间的整数或浮点数;'size'
(可选项):源码的字节大小。
字典中任何其他键会被忽略,以允许将来的扩展。 如果不能处理该路径,则会引发 OSError
。
3.3 新版功能.
在 3.4 版更改: 引发 OSError
而不是 NotImplemented
。
path_mtime
(path)返回指定文件路径修改时间的可选的抽象方法。
3.3 版后已移除: 在有了
path_stats()
的情况下,这个方法被弃用了。 没必要去实现它了,但是为了兼容性,它依然处于可用状态。 如果文件路径不能被处理,则引发OSError
异常。在 3.4 版更改: 引发
OSError
而不是NotImplemented
。set_data
(path, data)往一个文件路径写入指定字节的的可选的抽象方法。任何中间不存在的目录不会被自动创建。
由于路径是只读的,当写入的路径产生错误时(
errno.EACCES
/PermissionError
),不会传播异常。在 3.4 版更改: 当被调用时,不再引起
NotImplementedError
异常。get_code
(fullname)InspectLoader.get_code()
的具体实现。exec_module
(module)Loader.exec_module()
的具体实现。3.4 新版功能.
load_module
(fullname)Concrete implementation of
Loader.load_module()
.3.4 版后已移除: 使用
exec_module()
来代替。get_source
(fullname)InspectLoader.get_source()
的具体实现。is_package
(fullname)InspectLoader.is_package()
的具体实现。一个模块被确定为一个包的条件是:它的文件路径(由ExecutionLoader.get_filename()
提供)当文件扩展名被移除时是一个命名为__init__
的文件,并且 这个模块名字本身不是以__init__
结束。
class importlib.abc.Traversable
An object with a subset of pathlib.Path methods suitable for traversing directories and opening files.
3.9 新版功能.
class importlib.abc.TraversableResources
An abstract base class for resource readers capable of serving the files
interface. Subclasses ResourceReader and provides concrete implementations of the ResourceReader’s abstract methods. Therefore, any loader supplying TraversableReader also supplies ResourceReader.
Loaders that wish to support resource reading are expected to implement this interface.
3.9 新版功能.
importlib.resources
— 资源
源码: Lib/importlib/resources.py
3.7 新版功能.
这个模块使得Python的导入系统提供了访问包内的资源的功能。如果能够导入一个包,那么就能够访问那个包里面的资源。资源可以以二进制或文本模式方式被打开或读取。
资源非常类似于目录内部的文件,要牢记的是这仅仅是一个比喻。资源和包不是与文件系统上的物理文件和目录一样存在着。
注解
This module provides functionality similar to pkg_resources Basic Resource Access without the performance overhead of that package. This makes reading resources included in packages easier, with more stable and consistent semantics.
The standalone backport of this module provides more information on using importlib.resources and migrating from pkg_resources to importlib.resources.
加载器想要支持资源读取应该实现一个由 importlib.abc.ResourceReader
指定的get_resource_reader(fullname)
方法。
The following types are defined.
importlib.resources.Package
The Package
type is defined as Union[str, ModuleType]
. This means that where the function describes accepting a Package
, you can pass in either a string or a module. Module objects must have a resolvable __spec__.submodule_search_locations
that is not None
.
importlib.resources.Resource
This type describes the resource names passed into the various functions in this package. This is defined as Union[str, os.PathLike]
.
The following functions are available.
importlib.resources.files
(package)
Returns an importlib.resources.abc.Traversable
object representing the resource container for the package (think directory) and its resources (think files). A Traversable may contain other containers (think subdirectories).
package is either a name or a module object which conforms to the Package
requirements.
3.9 新版功能.
importlib.resources.as_file
(traversable)
Given a importlib.resources.abc.Traversable
object representing a file, typically from importlib.resources.files()
, return a context manager for use in a with
statement. The context manager provides a pathlib.Path
object.
Exiting the context manager cleans up any temporary file created when the resource was extracted from e.g. a zip file.
Use as_file
when the Traversable methods (read_text
, etc) are insufficient and an actual file on the file system is required.
3.9 新版功能.
importlib.resources.open_binary
(package, resource)
Open for binary reading the resource within package.
package is either a name or a module object which conforms to the Package
requirements. resource is the name of the resource to open within package; it may not contain path separators and it may not have sub-resources (i.e. it cannot be a directory). This function returns a typing.BinaryIO
instance, a binary I/O stream open for reading.
importlib.resources.open_text
(package, resource, encoding=’utf-8’, errors=’strict’)
Open for text reading the resource within package. By default, the resource is opened for reading as UTF-8.
package is either a name or a module object which conforms to the Package
requirements. resource is the name of the resource to open within package; it may not contain path separators and it may not have sub-resources (i.e. it cannot be a directory). encoding and errors have the same meaning as with built-in open()
.
This function returns a typing.TextIO
instance, a text I/O stream open for reading.
importlib.resources.read_binary
(package, resource)
Read and return the contents of the resource within package as bytes
.
package is either a name or a module object which conforms to the Package
requirements. resource is the name of the resource to open within package; it may not contain path separators and it may not have sub-resources (i.e. it cannot be a directory). This function returns the contents of the resource as bytes
.
importlib.resources.read_text
(package, resource, encoding=’utf-8’, errors=’strict’)
Read and return the contents of resource within package as a str
. By default, the contents are read as strict UTF-8.
package is either a name or a module object which conforms to the Package
requirements. resource is the name of the resource to open within package; it may not contain path separators and it may not have sub-resources (i.e. it cannot be a directory). encoding and errors have the same meaning as with built-in open()
. This function returns the contents of the resource as str
.
importlib.resources.path
(package, resource)
Return the path to the resource as an actual file system path. This function returns a context manager for use in a with
statement. The context manager provides a pathlib.Path
object.
Exiting the context manager cleans up any temporary file created when the resource needs to be extracted from e.g. a zip file.
package is either a name or a module object which conforms to the Package
requirements. resource is the name of the resource to open within package; it may not contain path separators and it may not have sub-resources (i.e. it cannot be a directory).
importlib.resources.is_resource
(package, name)
Return True
if there is a resource named name in the package, otherwise False
. Remember that directories are not resources! package is either a name or a module object which conforms to the Package
requirements.
importlib.resources.contents
(package)
Return an iterable over the named items within the package. The iterable returns str
resources (e.g. files) and non-resources (e.g. directories). The iterable does not recurse into subdirectories.
package is either a name or a module object which conforms to the Package
requirements.
importlib.machinery
— Importers and path hooks
Source code: Lib/importlib/machinery.py
This module contains the various objects that help import
find and load modules.
importlib.machinery.SOURCE_SUFFIXES
A list of strings representing the recognized file suffixes for source modules.
3.3 新版功能.
importlib.machinery.DEBUG_BYTECODE_SUFFIXES
A list of strings representing the file suffixes for non-optimized bytecode modules.
3.3 新版功能.
3.5 版后已移除: Use BYTECODE_SUFFIXES
instead.
importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES
A list of strings representing the file suffixes for optimized bytecode modules.
3.3 新版功能.
3.5 版后已移除: Use BYTECODE_SUFFIXES
instead.
importlib.machinery.BYTECODE_SUFFIXES
A list of strings representing the recognized file suffixes for bytecode modules (including the leading dot).
3.3 新版功能.
在 3.5 版更改: The value is no longer dependent on __debug__
.
importlib.machinery.EXTENSION_SUFFIXES
A list of strings representing the recognized file suffixes for extension modules.
3.3 新版功能.
importlib.machinery.all_suffixes
()
Returns a combined list of strings representing all file suffixes for modules recognized by the standard import machinery. This is a helper for code which simply needs to know if a filesystem path potentially refers to a module without needing any details on the kind of module (for example, inspect.getmodulename()
).
3.3 新版功能.
class importlib.machinery.BuiltinImporter
An importer for built-in modules. All known built-in modules are listed in sys.builtin_module_names
. This class implements the importlib.abc.MetaPathFinder
and importlib.abc.InspectLoader
ABCs.
Only class methods are defined by this class to alleviate the need for instantiation.
在 3.5 版更改: As part of PEP 489, the builtin importer now implements Loader.create_module()
and Loader.exec_module()
class importlib.machinery.FrozenImporter
An importer for frozen modules. This class implements the importlib.abc.MetaPathFinder
and importlib.abc.InspectLoader
ABCs.
Only class methods are defined by this class to alleviate the need for instantiation.
在 3.4 版更改: Gained create_module()
and exec_module()
methods.
class importlib.machinery.WindowsRegistryFinder
Finder for modules declared in the Windows registry. This class implements the importlib.abc.MetaPathFinder
ABC.
Only class methods are defined by this class to alleviate the need for instantiation.
3.3 新版功能.
3.6 版后已移除: Use site
configuration instead. Future versions of Python may not enable this finder by default.
class importlib.machinery.PathFinder
A Finder for sys.path
and package __path__
attributes. This class implements the importlib.abc.MetaPathFinder
ABC.
Only class methods are defined by this class to alleviate the need for instantiation.
classmethod
find_spec
(fullname, path=None, target=None)Class method that attempts to find a spec for the module specified by fullname on
sys.path
or, if defined, on path. For each path entry that is searched,sys.path_importer_cache
is checked. If a non-false object is found then it is used as the path entry finder to look for the module being searched for. If no entry is found insys.path_importer_cache
, thensys.path_hooks
is searched for a finder for the path entry and, if found, is stored insys.path_importer_cache
along with being queried about the module. If no finder is ever found thenNone
is both stored in the cache and returned.3.4 新版功能.
在 3.5 版更改: If the current working directory — represented by an empty string — is no longer valid then
None
is returned but no value is cached insys.path_importer_cache
.classmethod
find_module
(fullname, path=None)A legacy wrapper around
find_spec()
.3.4 版后已移除: 使用
find_spec()
来代替。classmethod
invalidate_caches
()Calls
importlib.abc.PathEntryFinder.invalidate_caches()
on all finders stored insys.path_importer_cache
that define the method. Otherwise entries insys.path_importer_cache
set toNone
are deleted.在 3.7 版更改: Entries of
None
insys.path_importer_cache
are deleted.
在 3.4 版更改: Calls objects in sys.path_hooks
with the current working directory for ''
(i.e. the empty string).
class importlib.machinery.FileFinder
(path, \loader_details*)
A concrete implementation of importlib.abc.PathEntryFinder
which caches results from the file system.
The path argument is the directory for which the finder is in charge of searching.
The loader_details argument is a variable number of 2-item tuples each containing a loader and a sequence of file suffixes the loader recognizes. The loaders are expected to be callables which accept two arguments of the module’s name and the path to the file found.
The finder will cache the directory contents as necessary, making stat calls for each module search to verify the cache is not outdated. Because cache staleness relies upon the granularity of the operating system’s state information of the file system, there is a potential race condition of searching for a module, creating a new file, and then searching for the module the new file represents. If the operations happen fast enough to fit within the granularity of stat calls, then the module search will fail. To prevent this from happening, when you create a module dynamically, make sure to call importlib.invalidate_caches()
.
3.3 新版功能.
path
The path the finder will search in.
find_spec
(fullname, target=None)Attempt to find the spec to handle fullname within
path
.3.4 新版功能.
find_loader
(fullname)Attempt to find the loader to handle fullname within
path
.3.10 版后已移除: 使用
find_spec()
来代替。invalidate_caches
()Clear out the internal cache.
classmethod
path_hook
(\loader_details*)A class method which returns a closure for use on
sys.path_hooks
. An instance ofFileFinder
is returned by the closure using the path argument given to the closure directly and loader_details indirectly.If the argument to the closure is not an existing directory,
ImportError
is raised.
class importlib.machinery.SourceFileLoader
(fullname, path)
A concrete implementation of importlib.abc.SourceLoader
by subclassing importlib.abc.FileLoader
and providing some concrete implementations of other methods.
3.3 新版功能.
name
The name of the module that this loader will handle.
path
The path to the source file.
is_package
(fullname)Return
True
ifpath
appears to be for a package.path_stats
(path)Concrete implementation of
importlib.abc.SourceLoader.path_stats()
.set_data
(path, data)Concrete implementation of
importlib.abc.SourceLoader.set_data()
.load_module
(name=None)Concrete implementation of
importlib.abc.Loader.load_module()
where specifying the name of the module to load is optional.3.6 版后已移除: Use
importlib.abc.Loader.exec_module()
instead.
class importlib.machinery.SourcelessFileLoader
(fullname, path)
A concrete implementation of importlib.abc.FileLoader
which can import bytecode files (i.e. no source code files exist).
Please note that direct use of bytecode files (and thus not source code files) inhibits your modules from being usable by all Python implementations or new versions of Python which change the bytecode format.
3.3 新版功能.
name
The name of the module the loader will handle.
path
The path to the bytecode file.
is_package
(fullname)Determines if the module is a package based on
path
.get_code
(fullname)Returns the code object for
name
created frompath
.get_source
(fullname)Returns
None
as bytecode files have no source when this loader is used.load_module
(name=None)
Concrete implementation of importlib.abc.Loader.load_module()
where specifying the name of the module to load is optional.
3.6 版后已移除: Use importlib.abc.Loader.exec_module()
instead.
class importlib.machinery.ExtensionFileLoader
(fullname, path)
A concrete implementation of importlib.abc.ExecutionLoader
for extension modules.
The fullname argument specifies the name of the module the loader is to support. The path argument is the path to the extension module’s file.
3.3 新版功能.
name
Name of the module the loader supports.
path
Path to the extension module.
create_module
(spec)Creates the module object from the given specification in accordance with PEP 489.
3.5 新版功能.
exec_module
(module)Initializes the given module object in accordance with PEP 489.
3.5 新版功能.
is_package
(fullname)Returns
True
if the file path points to a package’s__init__
module based onEXTENSION_SUFFIXES
.get_code
(fullname)Returns
None
as extension modules lack a code object.get_source
(fullname)Returns
None
as extension modules do not have source code.get_filename
(fullname)返回
path
。3.4 新版功能.
class importlib.machinery.ModuleSpec
(name, loader, **, origin=None, loader_state=None, is_package=None*)
A specification for a module’s import-system-related state. This is typically exposed as the module’s __spec__
attribute. In the descriptions below, the names in parentheses give the corresponding attribute available directly on the module object. E.g. module.__spec__.origin == module.__file__
. Note however that while the values are usually equivalent, they can differ since there is no synchronization between the two objects. Thus it is possible to update the module’s __path__
at runtime, and this will not be automatically reflected in __spec__.submodule_search_locations
.
3.4 新版功能.
name
(__name__
)
A string for the fully-qualified name of the module.
loader
(__loader__
)
The Loader that should be used when loading the module. Finders should always set this.
origin
(__file__
)
Name of the place from which the module is loaded, e.g. “builtin” for built-in modules and the filename for modules loaded from source. Normally “origin” should be set, but it may be None
(the default) which indicates it is unspecified (e.g. for namespace packages).
submodule_search_locations
(__path__
)
List of strings for where to find submodules, if a package (None
otherwise).
loader_state
Container of extra module-specific data for use during loading (or None
).
cached
(__cached__
)
String for where the compiled module should be stored (or None
).
parent
(__package__
)
(Read-only) The fully-qualified name of the package under which the module should be loaded as a submodule (or the empty string for top-level modules). For packages, it is the same as __name__
.
has_location
Boolean indicating whether or not the module’s “origin” attribute refers to a loadable location.
importlib.util
— Utility code for importers
Source code: Lib/importlib/util.py
This module contains the various objects that help in the construction of an importer.
importlib.util.MAGIC_NUMBER
The bytes which represent the bytecode version number. If you need help with loading/writing bytecode then consider importlib.abc.SourceLoader
.
3.4 新版功能.
importlib.util.cache_from_source
(path, debug_override=None, **, optimization=None*)
Return the PEP 3147/PEP 488 path to the byte-compiled file associated with the source path. For example, if path is /foo/bar/baz.py
the return value would be /foo/bar/__pycache__/baz.cpython-32.pyc
for Python 3.2. The cpython-32
string comes from the current magic tag (see get_tag()
; if sys.implementation.cache_tag
is not defined then NotImplementedError
will be raised).
The optimization parameter is used to specify the optimization level of the bytecode file. An empty string represents no optimization, so /foo/bar/baz.py
with an optimization of ''
will result in a bytecode path of /foo/bar/__pycache__/baz.cpython-32.pyc
. None
causes the interpreter’s optimization level to be used. Any other value’s string representation is used, so /foo/bar/baz.py
with an optimization of 2
will lead to the bytecode path of /foo/bar/__pycache__/baz.cpython-32.opt-2.pyc
. The string representation of optimization can only be alphanumeric, else ValueError
is raised.
The debug_override parameter is deprecated and can be used to override the system’s value for __debug__
. A True
value is the equivalent of setting optimization to the empty string. A False
value is the same as setting optimization to 1
. If both debug_override an optimization are not None
then TypeError
is raised.
3.4 新版功能.
在 3.5 版更改: The optimization parameter was added and the debug_override parameter was deprecated.
在 3.6 版更改: 接受一个 path-like object。
importlib.util.source_from_cache
(path)
Given the path to a PEP 3147 file name, return the associated source code file path. For example, if path is /foo/bar/__pycache__/baz.cpython-32.pyc
the returned path would be /foo/bar/baz.py
. path need not exist, however if it does not conform to PEP 3147 or PEP 488 format, a ValueError
is raised. If sys.implementation.cache_tag
is not defined, NotImplementedError
is raised.
3.4 新版功能.
在 3.6 版更改: 接受一个 path-like object。
importlib.util.decode_source
(source_bytes)
Decode the given bytes representing source code and return it as a string with universal newlines (as required by importlib.abc.InspectLoader.get_source()
).
3.4 新版功能.
importlib.util.resolve_name
(name, package)
Resolve a relative module name to an absolute one.
If name has no leading dots, then name is simply returned. This allows for usage such as importlib.util.resolve_name('sys', __spec__.parent)
without doing a check to see if the package argument is needed.
ImportError
is raised if name is a relative module name but package is a false value (e.g. None
or the empty string). ImportError
is also raised a relative name would escape its containing package (e.g. requesting ..bacon
from within the spam
package).
3.3 新版功能.
在 3.9 版更改: To improve consistency with import statements, raise ImportError
instead of ValueError
for invalid relative import attempts.
importlib.util.find_spec
(name, package=None)
Find the spec for a module, optionally relative to the specified package name. If the module is in sys.modules
, then sys.modules[name].__spec__
is returned (unless the spec would be None
or is not set, in which case ValueError
is raised). Otherwise a search using sys.meta_path
is done. None
is returned if no spec is found.
If name is for a submodule (contains a dot), the parent module is automatically imported.
name and package work the same as for import_module()
.
3.4 新版功能.
在 3.7 版更改: Raises ModuleNotFoundError
instead of AttributeError
if package is in fact not a package (i.e. lacks a __path__
attribute).
importlib.util.module_from_spec
(spec)
Create a new module based on spec and spec.loader.create_module
.
If spec.loader.create_module
does not return None
, then any pre-existing attributes will not be reset. Also, no AttributeError
will be raised if triggered while accessing spec or setting an attribute on the module.
This function is preferred over using types.ModuleType
to create a new module as spec is used to set as many import-controlled attributes on the module as possible.
3.5 新版功能.
@``importlib.util.module_for_loader
A decorator for importlib.abc.Loader.load_module()
to handle selecting the proper module object to load with. The decorated method is expected to have a call signature taking two positional arguments (e.g. load_module(self, module)
) for which the second argument will be the module object to be used by the loader. Note that the decorator will not work on static methods because of the assumption of two arguments.
The decorated method will take in the name of the module to be loaded as expected for a loader. If the module is not found in sys.modules
then a new one is constructed. Regardless of where the module came from, __loader__
set to self and __package__
is set based on what importlib.abc.InspectLoader.is_package()
returns (if available). These attributes are set unconditionally to support reloading.
If an exception is raised by the decorated method and a module was added to sys.modules
, then the module will be removed to prevent a partially initialized module from being in left in sys.modules
. If the module was already in sys.modules
then it is left alone.
在 3.3 版更改: __loader__
and __package__
are automatically set (when possible).
在 3.4 版更改: Set __name__
, __loader__
__package__
unconditionally to support reloading.
3.4 版后已移除: The import machinery now directly performs all the functionality provided by this function.
@``importlib.util.set_loader
A decorator for importlib.abc.Loader.load_module()
to set the __loader__
attribute on the returned module. If the attribute is already set the decorator does nothing. It is assumed that the first positional argument to the wrapped method (i.e. self
) is what __loader__
should be set to.
在 3.4 版更改: Set __loader__
if set to None
, as if the attribute does not exist.
3.4 版后已移除: The import machinery takes care of this automatically.
@``importlib.util.set_package
A decorator for importlib.abc.Loader.load_module()
to set the __package__
attribute on the returned module. If __package__
is set and has a value other than None
it will not be changed.
3.4 版后已移除: The import machinery takes care of this automatically.
importlib.util.spec_from_loader
(name, loader, **, origin=None, is_package=None*)
A factory function for creating a ModuleSpec
instance based on a loader. The parameters have the same meaning as they do for ModuleSpec. The function uses available loader APIs, such as InspectLoader.is_package()
, to fill in any missing information on the spec.
3.4 新版功能.
importlib.util.spec_from_file_location
(name, location, **, loader=None, submodule_search_locations=None*)
A factory function for creating a ModuleSpec
instance based on the path to a file. Missing information will be filled in on the spec by making use of loader APIs and by the implication that the module will be file-based.
3.4 新版功能.
在 3.6 版更改: 接受一个 path-like object。
importlib.util.source_hash
(source_bytes)
Return the hash of source_bytes as bytes. A hash-based .pyc
file embeds the source_hash()
of the corresponding source file’s contents in its header.
3.7 新版功能.
class importlib.util.LazyLoader
(loader)
A class which postpones the execution of the loader of a module until the module has an attribute accessed.
This class only works with loaders that define exec_module()
as control over what module type is used for the module is required. For those same reasons, the loader’s create_module()
method must return None
or a type for which its __class__
attribute can be mutated along with not using slots. Finally, modules which substitute the object placed into sys.modules
will not work as there is no way to properly replace the module references throughout the interpreter safely; ValueError
is raised if such a substitution is detected.
注解
For projects where startup time is critical, this class allows for potentially minimizing the cost of loading a module if it is never used. For projects where startup time is not essential then use of this class is heavily discouraged due to error messages created during loading being postponed and thus occurring out of context.
3.5 新版功能.
在 3.6 版更改: Began calling create_module()
, removing the compatibility warning for importlib.machinery.BuiltinImporter
and importlib.machinery.ExtensionFileLoader
.
classmethod
factory
(loader)A static method which returns a callable that creates a lazy loader. This is meant to be used in situations where the loader is passed by class instead of by instance.
suffixes = importlib.machinery.SOURCE_SUFFIXES loader = importlib.machinery.SourceFileLoader lazy_loader = importlib.util.LazyLoader.factory(loader) finder = importlib.machinery.FileFinder(path, (lazy_loader, suffixes))
例子
Importing programmatically
To programmatically import a module, use importlib.import_module()
.
import importlib
itertools = importlib.import_module('itertools')
Checking if a module can be imported
If you need to find out if a module can be imported without actually doing the import, then you should use importlib.util.find_spec()
.
import importlib.util
import sys
# For illustrative purposes.
name = 'itertools'
if name in sys.modules:
print(f"{name!r} already in sys.modules")
elif (spec := importlib.util.find_spec(name)) is not None:
# If you chose to perform the actual import ...
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)
print(f"{name!r} has been imported")
else:
print(f"can't find the {name!r} module")
Importing a source file directly
To import a Python source file directly, use the following recipe (Python 3.5 and newer only):
import importlib.util
import sys
# For illustrative purposes.
import tokenize
file_path = tokenize.__file__
module_name = tokenize.__name__
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)
Implementing lazy imports
The example below shows how to implement lazy imports:
>>> import importlib.util
>>> import sys
>>> def lazy_import(name):
... spec = importlib.util.find_spec(name)
... loader = importlib.util.LazyLoader(spec.loader)
... spec.loader = loader
... module = importlib.util.module_from_spec(spec)
... sys.modules[name] = module
... loader.exec_module(module)
... return module
...
>>> lazy_typing = lazy_import("typing")
>>> #lazy_typing is a real module object,
>>> #but it is not loaded in memory yet.
>>> lazy_typing.TYPE_CHECKING
False
Setting up an importer
For deep customizations of import, you typically want to implement an importer. This means managing both the finder and loader side of things. For finders there are two flavours to choose from depending on your needs: a meta path finder or a path entry finder. The former is what you would put on sys.meta_path
while the latter is what you create using a path entry hook on sys.path_hooks
which works with sys.path
entries to potentially create a finder. This example will show you how to register your own importers so that import will use them (for creating an importer for yourself, read the documentation for the appropriate classes defined within this package):
import importlib.machinery
import sys
# For illustrative purposes only.
SpamMetaPathFinder = importlib.machinery.PathFinder
SpamPathEntryFinder = importlib.machinery.FileFinder
loader_details = (importlib.machinery.SourceFileLoader,
importlib.machinery.SOURCE_SUFFIXES)
# Setting up a meta path finder.
# Make sure to put the finder in the proper location in the list in terms of
# priority.
sys.meta_path.append(SpamMetaPathFinder)
# Setting up a path entry finder.
# Make sure to put the path hook in the proper location in the list in terms
# of priority.
sys.path_hooks.append(SpamPathEntryFinder.path_hook(loader_details))
Approximating importlib.import_module()
Import itself is implemented in Python code, making it possible to expose most of the import machinery through importlib. The following helps illustrate the various APIs that importlib exposes by providing an approximate implementation of importlib.import_module()
(Python 3.4 and newer for the importlib usage, Python 3.6 and newer for other parts of the code).
import importlib.util
import sys
def import_module(name, package=None):
"""An approximate implementation of import."""
absolute_name = importlib.util.resolve_name(name, package)
try:
return sys.modules[absolute_name]
except KeyError:
pass
path = None
if '.' in absolute_name:
parent_name, _, child_name = absolute_name.rpartition('.')
parent_module = import_module(parent_name)
path = parent_module.__spec__.submodule_search_locations
for finder in sys.meta_path:
spec = finder.find_spec(absolute_name, path)
if spec is not None:
break
else:
msg = f'No module named {absolute_name!r}'
raise ModuleNotFoundError(msg, name=absolute_name)
module = importlib.util.module_from_spec(spec)
sys.modules[absolute_name] = module
spec.loader.exec_module(module)
if path is not None:
setattr(parent_module, child_name, module)
return module
Using importlib.metadata
Source code: Lib/importlib/metadata.py
Python 语言服务
Python 提供了许多模块来帮助使用 Python 语言。 这些模块支持标记化、解析、语法分析、字节码反汇编以及各种其他工具。
这些模块包括:
ast
—- 抽象语法树- 抽象文法
- 节点类
- 字面值
- Variables
- 表达式
- Subscripting
- Comprehensions
- Statements
- Imports
- Control flow
- Pattern matching
- Function and class definitions
- Async and await
ast
中的辅助函数- Compiler Flags
- Command-Line Usage
symtable
—- Access to the compiler’s symbol tables- Generating Symbol Tables
- Examining Symbol Tables
token
—- 与Python解析树一起使用的常量keyword
—- 检验Python关键字tokenize
—- 对 Python 代码使用的标记解析器- 对输入进行解析标记
- Command-Line Usage
- 例子
tabnanny
—- 模糊缩进检测pyclbr
—- Python 模块浏览器支持- Function 对象
- Class 对象
py_compile
—- 编译 Python 源文件- 命令行接口
compileall
—- Byte-compile Python libraries- Command-line use
- Public functions
dis
—- Python 字节码反汇编器- 字节码分析
- 分析函数
- Python字节码说明
- 操作码集合
pickletools
—- pickle 开发者工具集- 命令行语法
- 命令行选项
- 编程接口
- 命令行语法
ast
—- 抽象语法树
源代码: Lib/ast.py
ast
模块帮助 Python 程序处理 Python 语法的抽象语法树。抽象语法或许会随着 Python 的更新发布而改变;该模块能够帮助理解当前语法在编程层面的样貌。
抽象语法树可通过将 ast.PyCF_ONLY_AST
作为旗标传递给 compile()
内置函数来生成,或是使用此模块中提供的 parse()
辅助函数。返回结果将是一个对象树,,其中的类都继承自 ast.AST
。抽象语法树可被内置的 compile()
函数编译为一个 Python 代码对象。
抽象文法
抽象文法目前定义如下
-- ASDL's 4 builtin types are:
-- identifier, int, string, constant
module Python
{
mod = Module(stmt* body, type_ignore* type_ignores)
| Interactive(stmt* body)
| Expression(expr body)
| FunctionType(expr* argtypes, expr returns)
stmt = FunctionDef(identifier name, arguments args,
stmt* body, expr* decorator_list, expr? returns,
string? type_comment)
| AsyncFunctionDef(identifier name, arguments args,
stmt* body, expr* decorator_list, expr? returns,
string? type_comment)
| ClassDef(identifier name,
expr* bases,
keyword* keywords,
stmt* body,
expr* decorator_list)
| Return(expr? value)
| Delete(expr* targets)
| Assign(expr* targets, expr value, string? type_comment)
| AugAssign(expr target, operator op, expr value)
-- 'simple' indicates that we annotate simple name without parens
| AnnAssign(expr target, expr annotation, expr? value, int simple)
-- use 'orelse' because else is a keyword in target languages
| For(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
| AsyncFor(expr target, expr iter, stmt* body, stmt* orelse, string? type_comment)
| While(expr test, stmt* body, stmt* orelse)
| If(expr test, stmt* body, stmt* orelse)
| With(withitem* items, stmt* body, string? type_comment)
| AsyncWith(withitem* items, stmt* body, string? type_comment)
| Match(expr subject, match_case* cases)
| Raise(expr? exc, expr? cause)
| Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
| Assert(expr test, expr? msg)
| Import(alias* names)
| ImportFrom(identifier? module, alias* names, int? level)
| Global(identifier* names)
| Nonlocal(identifier* names)
| Expr(expr value)
| Pass | Break | Continue
-- col_offset is the byte offset in the utf8 string the parser uses
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- BoolOp() can use left & right?
expr = BoolOp(boolop op, expr* values)
| NamedExpr(expr target, expr value)
| BinOp(expr left, operator op, expr right)
| UnaryOp(unaryop op, expr operand)
| Lambda(arguments args, expr body)
| IfExp(expr test, expr body, expr orelse)
| Dict(expr* keys, expr* values)
| Set(expr* elts)
| ListComp(expr elt, comprehension* generators)
| SetComp(expr elt, comprehension* generators)
| DictComp(expr key, expr value, comprehension* generators)
| GeneratorExp(expr elt, comprehension* generators)
-- the grammar constrains where yield expressions can occur
| Await(expr value)
| Yield(expr? value)
| YieldFrom(expr value)
-- need sequences for compare to distinguish between
-- x < 4 < 3 and (x < 4) < 3
| Compare(expr left, cmpop* ops, expr* comparators)
| Call(expr func, expr* args, keyword* keywords)
| FormattedValue(expr value, int? conversion, expr? format_spec)
| JoinedStr(expr* values)
| Constant(constant value, string? kind)
-- the following expression can appear in assignment context
| Attribute(expr value, identifier attr, expr_context ctx)
| Subscript(expr value, expr slice, expr_context ctx)
| Starred(expr value, expr_context ctx)
| Name(identifier id, expr_context ctx)
| List(expr* elts, expr_context ctx)
| Tuple(expr* elts, expr_context ctx)
-- can appear only in Subscript
| Slice(expr? lower, expr? upper, expr? step)
-- col_offset is the byte offset in the utf8 string the parser uses
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
expr_context = Load | Store | Del
boolop = And | Or
operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift
| RShift | BitOr | BitXor | BitAnd | FloorDiv
unaryop = Invert | Not | UAdd | USub
cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn
comprehension = (expr target, expr iter, expr* ifs, int is_async)
excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
arguments = (arg* posonlyargs, arg* args, arg? vararg, arg* kwonlyargs,
expr* kw_defaults, arg? kwarg, expr* defaults)
arg = (identifier arg, expr? annotation, string? type_comment)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- keyword arguments supplied to call (NULL identifier for **kwargs)
keyword = (identifier? arg, expr value)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
-- import name with optional 'as' alias.
alias = (identifier name, identifier? asname)
attributes (int lineno, int col_offset, int? end_lineno, int? end_col_offset)
withitem = (expr context_expr, expr? optional_vars)
match_case = (pattern pattern, expr? guard, stmt* body)
pattern = MatchValue(expr value)
| MatchSingleton(constant value)
| MatchSequence(pattern* patterns)
| MatchMapping(expr* keys, pattern* patterns, identifier? rest)
| MatchClass(expr cls, pattern* patterns, identifier* kwd_attrs, pattern* kwd_patterns)
| MatchStar(identifier? name)
-- The optional "rest" MatchMapping parameter handles capturing extra mapping keys
| MatchAs(pattern? pattern, identifier? name)
| MatchOr(pattern* patterns)
attributes (int lineno, int col_offset, int end_lineno, int end_col_offset)
type_ignore = TypeIgnore(int lineno, string tag)
}
节点类
class ast.AST
这是所有 AST 节点类的基类。实际上,这些节点类派生自 Parser/Python.asdl
文件,其中定义的语法树示例 如下。它们在 C 语言模块 _ast
中定义,并被导出至 ast
模块。
抽象语法定义的每个左侧符号(比方说, ast.stmt
或者 ast.expr
)定义了一个类。另外,在抽象语法定义的右侧,对每一个构造器也定义了一个类;这些类继承自树左侧的类。比如,ast.BinOp
继承自 ast.expr
。对于多分支产生式(也就是”和规则”),树右侧的类是抽象的;只有特定构造器结点的实例能被构造。
_fields
每个具体类都有个属性
_fields
, 用来给出所有子节点的名字。每个具体类的实例对它每个子节点都有一个属性,对应类型如文法中所定义。比如,
ast.BinOp
的实例有个属性left
,类型是ast.expr
.如果这些属性在文法中标记为可选(使用问号),对应值可能会是
None
。如果这些属性有零或多个(用星号标记),对应值会用Python的列表来表示。所有可能的属性必须在用compile()
编译得到AST时给出,且是有效的值。lineno
col_offset
end_lineno
end_col_offset
Instances of
ast.expr
andast.stmt
subclasses havelineno
,col_offset
,end_lineno
, andend_col_offset
attributes. Thelineno
andend_lineno
are the first and last line numbers of source text span (1-indexed so the first line is line 1) and thecol_offset
andend_col_offset
are the corresponding UTF-8 byte offsets of the first and last tokens that generated the node. The UTF-8 offset is recorded because the parser uses UTF-8 internally.Note that the end positions are not required by the compiler and are therefore optional. The end offset is after the last symbol, for example one can get the source segment of a one-line expression node using
source_line[node.col_offset : node.end_col_offset]
.
一个类的构造器 ast.T
像下面这样parse它的参数。
- 如果有位置参数,它们必须和
T._fields
中的元素一样多;他们会像这些名字的属性一样被赋值。 - 如果有关键字参数,它们必须被设为和给定值同名的属性。
比方说,要创建和填充节点 ast.UnaryOp
,你得用
node = ast.UnaryOp()
node.op = ast.USub()
node.operand = ast.Constant()
node.operand.value = 5
node.operand.lineno = 0
node.operand.col_offset = 0
node.lineno = 0
node.col_offset = 0
或者更紧凑点
node = ast.UnaryOp(ast.USub(), ast.Constant(5, lineno=0, col_offset=0),
lineno=0, col_offset=0)
在 3.8 版更改: Class ast.Constant
is now used for all constants.
在 3.9 版更改: Simple indices are represented by their value, extended slices are represented as tuples.
3.8 版后已移除: Old classes ast.Num
, ast.Str
, ast.Bytes
, ast.NameConstant
and ast.Ellipsis
are still available, but they will be removed in future Python releases. In the meantime, instantiating them will return an instance of a different class.
3.9 版后已移除: Old classes ast.Index
and ast.ExtSlice
are still available, but they will be removed in future Python releases. In the meantime, instantiating them will return an instance of a different class.
注解
The descriptions of the specific node classes displayed here were initially adapted from the fantastic Green Tree Snakes project and all its contributors.
字面值
class ast.Constant
(value)
A constant value. The value
attribute of the Constant
literal contains the Python object it represents. The values represented can be simple types such as a number, string or None
, but also immutable container types (tuples and frozensets) if all of their elements are constant.
>>> print(ast.dump(ast.parse('123', mode='eval'), indent=4))
Expression(
body=Constant(value=123))
class ast.FormattedValue
(value, conversion, format_spec)
Node representing a single formatting field in an f-string. If the string contains a single formatting field and nothing else the node can be isolated otherwise it appears in JoinedStr
.
value
is any expression node (such as a literal, a variable, or a function call).conversion
is an integer:- -1: no formatting
- 115:
!s
string formatting - 114:
!r
repr formatting - 97:
!a
ascii formatting
format_spec
is aJoinedStr
node representing the formatting of the value, orNone
if no format was specified. Bothconversion
andformat_spec
can be set at the same time.
class ast.JoinedStr
(values)
An f-string, comprising a series of FormattedValue
and Constant
nodes.
>>> print(ast.dump(ast.parse('f"sin({a}) is {sin(a):.3}"', mode='eval'), indent=4))
Expression(
body=JoinedStr(
values=[
Constant(value='sin('),
FormattedValue(
value=Name(id='a', ctx=Load()),
conversion=-1),
Constant(value=') is '),
FormattedValue(
value=Call(
func=Name(id='sin', ctx=Load()),
args=[
Name(id='a', ctx=Load())],
keywords=[]),
conversion=-1,
format_spec=JoinedStr(
values=[
Constant(value='.3')]))]))
class ast.List
(elts, ctx)
class ast.Tuple
(elts, ctx)
A list or tuple. elts
holds a list of nodes representing the elements. ctx
is Store
if the container is an assignment target (i.e. (x,y)=something
), and Load
otherwise.
>>> print(ast.dump(ast.parse('[1, 2, 3]', mode='eval'), indent=4))
Expression(
body=List(
elts=[
Constant(value=1),
Constant(value=2),
Constant(value=3)],
ctx=Load()))
>>> print(ast.dump(ast.parse('(1, 2, 3)', mode='eval'), indent=4))
Expression(
body=Tuple(
elts=[
Constant(value=1),
Constant(value=2),
Constant(value=3)],
ctx=Load()))
class ast.Set
(elts)
A set. elts
holds a list of nodes representing the set’s elements.
>>> print(ast.dump(ast.parse('{1, 2, 3}', mode='eval'), indent=4))
Expression(
body=Set(
elts=[
Constant(value=1),
Constant(value=2),
Constant(value=3)]))
class ast.Dict
(keys, values)
A dictionary. keys
and values
hold lists of nodes representing the keys and the values respectively, in matching order (what would be returned when calling dictionary.keys()
and dictionary.values()
).
When doing dictionary unpacking using dictionary literals the expression to be expanded goes in the values
list, with a None
at the corresponding position in keys
.
>>> print(ast.dump(ast.parse('{"a":1, **d}', mode='eval'), indent=4))
Expression(
body=Dict(
keys=[
Constant(value='a'),
None],
values=[
Constant(value=1),
Name(id='d', ctx=Load())]))
Variables
class ast.Name
(id, ctx)
A variable name. id
holds the name as a string, and ctx
is one of the following types.
class ast.Load
class ast.Store
class ast.Del
Variable references can be used to load the value of a variable, to assign a new value to it, or to delete it. Variable references are given a context to distinguish these cases.
>>> print(ast.dump(ast.parse('a'), indent=4))
Module(
body=[
Expr(
value=Name(id='a', ctx=Load()))],
type_ignores=[])
>>> print(ast.dump(ast.parse('a = 1'), indent=4))
Module(
body=[
Assign(
targets=[
Name(id='a', ctx=Store())],
value=Constant(value=1))],
type_ignores=[])
>>> print(ast.dump(ast.parse('del a'), indent=4))
Module(
body=[
Delete(
targets=[
Name(id='a', ctx=Del())])],
type_ignores=[])
class ast.Starred
(value, ctx)
A *var
variable reference. value
holds the variable, typically a Name
node. This type must be used when building a Call
node with *args
.
>>> print(ast.dump(ast.parse('a, *b = it'), indent=4))
Module(
body=[
Assign(
targets=[
Tuple(
elts=[
Name(id='a', ctx=Store()),
Starred(
value=Name(id='b', ctx=Store()),
ctx=Store())],
ctx=Store())],
value=Name(id='it', ctx=Load()))],
type_ignores=[])
表达式
class ast.Expr
(value)
When an expression, such as a function call, appears as a statement by itself with its return value not used or stored, it is wrapped in this container. value
holds one of the other nodes in this section, a Constant
, a Name
, a Lambda
, a Yield
or YieldFrom
node.
>>> print(ast.dump(ast.parse('-a'), indent=4))
Module(
body=[
Expr(
value=UnaryOp(
op=USub(),
operand=Name(id='a', ctx=Load())))],
type_ignores=[])
class ast.UnaryOp
(op, operand)
A unary operation. op
is the operator, and operand
any expression node.
class ast.UAdd
class ast.USub
class ast.Not
class ast.Invert
Unary operator tokens. Not
is the not
keyword, Invert
is the ~
operator.
>>> print(ast.dump(ast.parse('not x', mode='eval'), indent=4))
Expression(
body=UnaryOp(
op=Not(),
operand=Name(id='x', ctx=Load())))
class ast.BinOp
(left, op, right)
A binary operation (like addition or division). op
is the operator, and left
and right
are any expression nodes.
>>> print(ast.dump(ast.parse('x + y', mode='eval'), indent=4))
Expression(
body=BinOp(
left=Name(id='x', ctx=Load()),
op=Add(),
right=Name(id='y', ctx=Load())))
class ast.Add
class ast.Sub
class ast.Mult
class ast.Div
class ast.FloorDiv
class ast.Mod
class ast.Pow
class ast.LShift
class ast.RShift
class ast.BitOr
class ast.BitXor
class ast.BitAnd
class ast.MatMult
Binary operator tokens.
class ast.BoolOp
(op, values)
A boolean operation, ‘or’ or ‘and’. op
is Or
or And
. values
are the values involved. Consecutive operations with the same operator, such as a or b or c
, are collapsed into one node with several values.
This doesn’t include not
, which is a UnaryOp
.
>>> print(ast.dump(ast.parse('x or y', mode='eval'), indent=4))
Expression(
body=BoolOp(
op=Or(),
values=[
Name(id='x', ctx=Load()),
Name(id='y', ctx=Load())]))
class ast.And
class ast.Or
Boolean operator tokens.
class ast.Compare
(left, ops, comparators)
A comparison of two or more values. left
is the first value in the comparison, ops
the list of operators, and comparators
the list of values after the first element in the comparison.
>>> print(ast.dump(ast.parse('1 <= a < 10', mode='eval'), indent=4))
Expression(
body=Compare(
left=Constant(value=1),
ops=[
LtE(),
Lt()],
comparators=[
Name(id='a', ctx=Load()),
Constant(value=10)]))
class ast.Eq
class ast.NotEq
class ast.Lt
class ast.LtE
class ast.Gt
class ast.GtE
class ast.Is
class ast.IsNot
class ast.In
class ast.NotIn
Comparison operator tokens.
class ast.Call
(func, args, keywords, starargs, kwargs)
A function call. func
is the function, which will often be a Name
or Attribute
object. Of the arguments:
args
holds a list of the arguments passed by position.keywords
holds a list ofkeyword
objects representing arguments passed by keyword.
When creating a Call
node, args
and keywords
are required, but they can be empty lists. starargs
and kwargs
are optional.
>>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)', mode='eval'), indent=4))
Expression(
body=Call(
func=Name(id='func', ctx=Load()),
args=[
Name(id='a', ctx=Load()),
Starred(
value=Name(id='d', ctx=Load()),
ctx=Load())],
keywords=[
keyword(
arg='b',
value=Name(id='c', ctx=Load())),
keyword(
value=Name(id='e', ctx=Load()))]))
class ast.keyword
(arg, value)
A keyword argument to a function call or class definition. arg
is a raw string of the parameter name, value
is a node to pass in.
class ast.IfExp
(test, body, orelse)
An expression such as a if b else c
. Each field holds a single node, so in the following example, all three are Name
nodes.
>>> print(ast.dump(ast.parse('a if b else c', mode='eval'), indent=4))
Expression(
body=IfExp(
test=Name(id='b', ctx=Load()),
body=Name(id='a', ctx=Load()),
orelse=Name(id='c', ctx=Load())))
class ast.Attribute
(value, attr, ctx)
Attribute access, e.g. d.keys
. value
is a node, typically a Name
. attr
is a bare string giving the name of the attribute, and ctx
is Load
, Store
or Del
according to how the attribute is acted on.
>>> print(ast.dump(ast.parse('snake.colour', mode='eval'), indent=4))
Expression(
body=Attribute(
value=Name(id='snake', ctx=Load()),
attr='colour',
ctx=Load()))
class ast.NamedExpr
(target, value)
A named expression. This AST node is produced by the assignment expressions operator (also known as the walrus operator). As opposed to the
Assign
node in which the first argument can be multiple nodes, in this case bothtarget
andvalue
must be single nodes.
>>> print(ast.dump(ast.parse('(x := 4)', mode='eval'), indent=4))
Expression(
body=NamedExpr(
target=Name(id='x', ctx=Store()),
value=Constant(value=4)))
Subscripting
class ast.Subscript
(value, slice, ctx)
A subscript, such as l[1]
. value
is the subscripted object (usually sequence or mapping). slice
is an index, slice or key. It can be a Tuple
and contain a Slice
. ctx
is Load
, Store
or Del
according to the action performed with the subscript.
>>> print(ast.dump(ast.parse('l[1:2, 3]', mode='eval'), indent=4))
Expression(
body=Subscript(
value=Name(id='l', ctx=Load()),
slice=Tuple(
elts=[
Slice(
lower=Constant(value=1),
upper=Constant(value=2)),
Constant(value=3)],
ctx=Load()),
ctx=Load()))
class ast.Slice
(lower, upper, step)
Regular slicing (on the form lower:upper
or lower:upper:step
). Can occur only inside the slice field of Subscript
, either directly or as an element of Tuple
.
>>> print(ast.dump(ast.parse('l[1:2]', mode='eval'), indent=4))
Expression(
body=Subscript(
value=Name(id='l', ctx=Load()),
slice=Slice(
lower=Constant(value=1),
upper=Constant(value=2)),
ctx=Load()))
Comprehensions
class ast.ListComp
(elt, generators)
class ast.SetComp
(elt, generators)
class ast.GeneratorExp
(elt, generators)
class ast.DictComp
(key, value, generators)
List and set comprehensions, generator expressions, and dictionary comprehensions. elt
(or key
and value
) is a single node representing the part that will be evaluated for each item.
generators
is a list of comprehension
nodes.
>>> print(ast.dump(ast.parse('[x for x in numbers]', mode='eval'), indent=4))
Expression(
body=ListComp(
elt=Name(id='x', ctx=Load()),
generators=[
comprehension(
target=Name(id='x', ctx=Store()),
iter=Name(id='numbers', ctx=Load()),
ifs=[],
is_async=0)]))
>>> print(ast.dump(ast.parse('{x: x**2 for x in numbers}', mode='eval'), indent=4))
Expression(
body=DictComp(
key=Name(id='x', ctx=Load()),
value=BinOp(
left=Name(id='x', ctx=Load()),
op=Pow(),
right=Constant(value=2)),
generators=[
comprehension(
target=Name(id='x', ctx=Store()),
iter=Name(id='numbers', ctx=Load()),
ifs=[],
is_async=0)]))
>>> print(ast.dump(ast.parse('{x for x in numbers}', mode='eval'), indent=4))
Expression(
body=SetComp(
elt=Name(id='x', ctx=Load()),
generators=[
comprehension(
target=Name(id='x', ctx=Store()),
iter=Name(id='numbers', ctx=Load()),
ifs=[],
is_async=0)]))
class ast.comprehension
(target, iter, ifs, is_async)
One for
clause in a comprehension. target
is the reference to use for each element - typically a Name
or Tuple
node. iter
is the object to iterate over. ifs
is a list of test expressions: each for
clause can have multiple ifs
.
is_async
indicates a comprehension is asynchronous (using an async for
instead of for
). The value is an integer (0 or 1).
>>> print(ast.dump(ast.parse('[ord(c) for line in file for c in line]', mode='eval'),
... indent=4)) # Multiple comprehensions in one.
Expression(
body=ListComp(
elt=Call(
func=Name(id='ord', ctx=Load()),
args=[
Name(id='c', ctx=Load())],
keywords=[]),
generators=[
comprehension(
target=Name(id='line', ctx=Store()),
iter=Name(id='file', ctx=Load()),
ifs=[],
is_async=0),
comprehension(
target=Name(id='c', ctx=Store()),
iter=Name(id='line', ctx=Load()),
ifs=[],
is_async=0)]))
>>> print(ast.dump(ast.parse('(n**2 for n in it if n>5 if n<10)', mode='eval'),
... indent=4)) # generator comprehension
Expression(
body=GeneratorExp(
elt=BinOp(
left=Name(id='n', ctx=Load()),
op=Pow(),
right=Constant(value=2)),
generators=[
comprehension(
target=Name(id='n', ctx=Store()),
iter=Name(id='it', ctx=Load()),
ifs=[
Compare(
left=Name(id='n', ctx=Load()),
ops=[
Gt()],
comparators=[
Constant(value=5)]),
Compare(
left=Name(id='n', ctx=Load()),
ops=[
Lt()],
comparators=[
Constant(value=10)])],
is_async=0)]))
>>> print(ast.dump(ast.parse('[i async for i in soc]', mode='eval'),
... indent=4)) # Async comprehension
Expression(
body=ListComp(
elt=Name(id='i', ctx=Load()),
generators=[
comprehension(
target=Name(id='i', ctx=Store()),
iter=Name(id='soc', ctx=Load()),
ifs=[],
is_async=1)]))
Statements
class ast.Assign
(targets, value, type_comment)
An assignment. targets
is a list of nodes, and value
is a single node.
Multiple nodes in targets
represents assigning the same value to each. Unpacking is represented by putting a Tuple
or List
within targets
.
type_comment
type_comment
is an optional string with the type annotation as a comment.
>>> print(ast.dump(ast.parse('a = b = 1'), indent=4)) # Multiple assignment
Module(
body=[
Assign(
targets=[
Name(id='a', ctx=Store()),
Name(id='b', ctx=Store())],
value=Constant(value=1))],
type_ignores=[])
>>> print(ast.dump(ast.parse('a,b = c'), indent=4)) # Unpacking
Module(
body=[
Assign(
targets=[
Tuple(
elts=[
Name(id='a', ctx=Store()),
Name(id='b', ctx=Store())],
ctx=Store())],
value=Name(id='c', ctx=Load()))],
type_ignores=[])
class ast.AnnAssign
(target, annotation, value, simple)
An assignment with a type annotation. target
is a single node and can be a Name
, a Attribute
or a Subscript
. annotation
is the annotation, such as a Constant
or Name
node. value
is a single optional node. simple
is a boolean integer set to True for a Name
node in target
that do not appear in between parenthesis and are hence pure names and not expressions.
>>> print(ast.dump(ast.parse('c: int'), indent=4))
Module(
body=[
AnnAssign(
target=Name(id='c', ctx=Store()),
annotation=Name(id='int', ctx=Load()),
simple=1)],
type_ignores=[])
>>> print(ast.dump(ast.parse('(a): int = 1'), indent=4)) # Annotation with parenthesis
Module(
body=[
AnnAssign(
target=Name(id='a', ctx=Store()),
annotation=Name(id='int', ctx=Load()),
value=Constant(value=1),
simple=0)],
type_ignores=[])
>>> print(ast.dump(ast.parse('a.b: int'), indent=4)) # Attribute annotation
Module(
body=[
AnnAssign(
target=Attribute(
value=Name(id='a', ctx=Load()),
attr='b',
ctx=Store()),
annotation=Name(id='int', ctx=Load()),
simple=0)],
type_ignores=[])
>>> print(ast.dump(ast.parse('a[1]: int'), indent=4)) # Subscript annotation
Module(
body=[
AnnAssign(
target=Subscript(
value=Name(id='a', ctx=Load()),
slice=Constant(value=1),
ctx=Store()),
annotation=Name(id='int', ctx=Load()),
simple=0)],
type_ignores=[])
class ast.AugAssign
(target, op, value)
Augmented assignment, such as a += 1
. In the following example, target
is a Name
node for x
(with the Store
context), op
is Add
, and value
is a Constant
with value for 1.
The target
attribute cannot be of class Tuple
or List
, unlike the targets of Assign
.
>>> print(ast.dump(ast.parse('x += 2'), indent=4))
Module(
body=[
AugAssign(
target=Name(id='x', ctx=Store()),
op=Add(),
value=Constant(value=2))],
type_ignores=[])
class ast.Raise
(exc, cause)
A raise
statement. exc
is the exception object to be raised, normally a Call
or Name
, or None
for a standalone raise
. cause
is the optional part for y
in raise x from y
.
>>> print(ast.dump(ast.parse('raise x from y'), indent=4))
Module(
body=[
Raise(
exc=Name(id='x', ctx=Load()),
cause=Name(id='y', ctx=Load()))],
type_ignores=[])
class ast.Assert
(test, msg)
An assertion. test
holds the condition, such as a Compare
node. msg
holds the failure message.
>>> print(ast.dump(ast.parse('assert x,y'), indent=4))
Module(
body=[
Assert(
test=Name(id='x', ctx=Load()),
msg=Name(id='y', ctx=Load()))],
type_ignores=[])
class ast.Delete
(targets)
Represents a del
statement. targets
is a list of nodes, such as Name
, Attribute
or Subscript
nodes.
>>> print(ast.dump(ast.parse('del x,y,z'), indent=4))
Module(
body=[
Delete(
targets=[
Name(id='x', ctx=Del()),
Name(id='y', ctx=Del()),
Name(id='z', ctx=Del())])],
type_ignores=[])
class ast.Pass
A pass
statement.
>>> print(ast.dump(ast.parse('pass'), indent=4))
Module(
body=[
Pass()],
type_ignores=[])
Other statements which are only applicable inside functions or loops are described in other sections.
Imports
class ast.Import
(names)
An import statement. names
is a list of alias
nodes.
>>> print(ast.dump(ast.parse('import x,y,z'), indent=4))
Module(
body=[
Import(
names=[
alias(name='x'),
alias(name='y'),
alias(name='z')])],
type_ignores=[])
class ast.ImportFrom
(module, names, level)
Represents from x import y
. module
is a raw string of the ‘from’ name, without any leading dots, or None
for statements such as from . import foo
. level
is an integer holding the level of the relative import (0 means absolute import).
>>> print(ast.dump(ast.parse('from y import x,y,z'), indent=4))
Module(
body=[
ImportFrom(
module='y',
names=[
alias(name='x'),
alias(name='y'),
alias(name='z')],
level=0)],
type_ignores=[])
class ast.alias
(name, asname)
Both parameters are raw strings of the names. asname
can be None
if the regular name is to be used.
>>> print(ast.dump(ast.parse('from ..foo.bar import a as b, c'), indent=4))
Module(
body=[
ImportFrom(
module='foo.bar',
names=[
alias(name='a', asname='b'),
alias(name='c')],
level=2)],
type_ignores=[])
Control flow
注解
Optional clauses such as else
are stored as an empty list if they’re not present.
class ast.If
(test, body, orelse)
An if
statement. test
holds a single node, such as a Compare
node. body
and orelse
each hold a list of nodes.
elif
clauses don’t have a special representation in the AST, but rather appear as extra If
nodes within the orelse
section of the previous one.
>>> print(ast.dump(ast.parse("""
... if x:
... ...
... elif y:
... ...
... else:
... ...
... """), indent=4))
Module(
body=[
If(
test=Name(id='x', ctx=Load()),
body=[
Expr(
value=Constant(value=Ellipsis))],
orelse=[
If(
test=Name(id='y', ctx=Load()),
body=[
Expr(
value=Constant(value=Ellipsis))],
orelse=[
Expr(
value=Constant(value=Ellipsis))])])],
type_ignores=[])
class ast.For
(target, iter, body, orelse, type_comment)
A for
loop. target
holds the variable(s) the loop assigns to, as a single Name
, Tuple
or List
node. iter
holds the item to be looped over, again as a single node. body
and orelse
contain lists of nodes to execute. Those in orelse
are executed if the loop finishes normally, rather than via a break
statement.
type_comment
type_comment
is an optional string with the type annotation as a comment.
>>> print(ast.dump(ast.parse("""
... for x in y:
... ...
... else:
... ...
... """), indent=4))
Module(
body=[
For(
target=Name(id='x', ctx=Store()),
iter=Name(id='y', ctx=Load()),
body=[
Expr(
value=Constant(value=Ellipsis))],
orelse=[
Expr(
value=Constant(value=Ellipsis))])],
type_ignores=[])
class ast.While
(test, body, orelse)
A while
loop. test
holds the condition, such as a Compare
node.
>> print(ast.dump(ast.parse("""
... while x:
... ...
... else:
... ...
... """), indent=4))
Module(
body=[
While(
test=Name(id='x', ctx=Load()),
body=[
Expr(
value=Constant(value=Ellipsis))],
orelse=[
Expr(
value=Constant(value=Ellipsis))])],
type_ignores=[])
class ast.Break
class ast.Continue
The break
and continue
statements.
>>> print(ast.dump(ast.parse("""\
... for a in b:
... if a > 5:
... break
... else:
... continue
...
... """), indent=4))
Module(
body=[
For(
target=Name(id='a', ctx=Store()),
iter=Name(id='b', ctx=Load()),
body=[
If(
test=Compare(
left=Name(id='a', ctx=Load()),
ops=[
Gt()],
comparators=[
Constant(value=5)]),
body=[
Break()],
orelse=[
Continue()])],
orelse=[])],
type_ignores=[])
class ast.Try
(body, handlers, orelse, finalbody)
try
blocks. All attributes are list of nodes to execute, except for handlers
, which is a list of ExceptHandler
nodes.
>>> print(ast.dump(ast.parse("""
... try:
... ...
... except Exception:
... ...
... except OtherException as e:
... ...
... else:
... ...
... finally:
... ...
... """), indent=4))
Module(
body=[
Try(
body=[
Expr(
value=Constant(value=Ellipsis))],
handlers=[
ExceptHandler(
type=Name(id='Exception', ctx=Load()),
body=[
Expr(
value=Constant(value=Ellipsis))]),
ExceptHandler(
type=Name(id='OtherException', ctx=Load()),
name='e',
body=[
Expr(
value=Constant(value=Ellipsis))])],
orelse=[
Expr(
value=Constant(value=Ellipsis))],
finalbody=[
Expr(
value=Constant(value=Ellipsis))])],
type_ignores=[])
class ast.ExceptHandler
(type, name, body)
A single except
clause. type
is the exception type it will match, typically a Name
node (or None
for a catch-all except:
clause). name
is a raw string for the name to hold the exception, or None
if the clause doesn’t have as foo
. body
is a list of nodes.
>>> print(ast.dump(ast.parse("""\
... try:
... a + 1
... except TypeError:
... pass
... """), indent=4))
Module(
body=[
Try(
body=[
Expr(
value=BinOp(
left=Name(id='a', ctx=Load()),
op=Add(),
right=Constant(value=1)))],
handlers=[
ExceptHandler(
type=Name(id='TypeError', ctx=Load()),
body=[
Pass()])],
orelse=[],
finalbody=[])],
type_ignores=[])
class ast.With
(items, body, type_comment)
A with
block. items
is a list of withitem
nodes representing the context managers, and body
is the indented block inside the context.
type_comment
type_comment
is an optional string with the type annotation as a comment.
class ast.withitem
(context_expr, optional_vars)
A single context manager in a with
block. context_expr
is the context manager, often a Call
node. optional_vars
is a Name
, Tuple
or List
for the as foo
part, or None
if that isn’t used.
>>> print(ast.dump(ast.parse("""\
... with a as b, c as d:
... something(b, d)
... """), indent=4))
Module(
body=[
With(
items=[
withitem(
context_expr=Name(id='a', ctx=Load()),
optional_vars=Name(id='b', ctx=Store())),
withitem(
context_expr=Name(id='c', ctx=Load()),
optional_vars=Name(id='d', ctx=Store()))],
body=[
Expr(
value=Call(
func=Name(id='something', ctx=Load()),
args=[
Name(id='b', ctx=Load()),
Name(id='d', ctx=Load())],
keywords=[]))])],
type_ignores=[])
Pattern matching
class ast.Match
(subject, cases)
A match
statement. subject
holds the subject of the match (the object that is being matched against the cases) and cases
contains an iterable of match_case
nodes with the different cases.
class ast.match_case
(pattern, guard, body)
A single case pattern in a match
statement. pattern
contains the match pattern that the subject will be matched against. Note that the AST
nodes produced for patterns differ from those produced for expressions, even when they share the same syntax.
The guard
attribute contains an expression that will be evaluated if the pattern matches the subject.
body
contains a list of nodes to execute if the pattern matches and the result of evaluating the guard expression is true.
>>> print(ast.dump(ast.parse("""
... match x:
... case [x] if x>0:
... ...
... case tuple():
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchSequence(
patterns=[
MatchAs(name='x')]),
guard=Compare(
left=Name(id='x', ctx=Load()),
ops=[
Gt()],
comparators=[
Constant(value=0)]),
body=[
Expr(
value=Constant(value=Ellipsis))]),
match_case(
pattern=MatchClass(
cls=Name(id='tuple', ctx=Load()),
patterns=[],
kwd_attrs=[],
kwd_patterns=[]),
body=[
Expr(
value=Constant(value=Ellipsis))])])],
type_ignores=[])
class ast.MatchValue
(value)
A match literal or value pattern that compares by equality. value
is an expression node. Permitted value nodes are restricted as described in the match statement documentation. This pattern succeeds if the match subject is equal to the evaluated value.
>>> print(ast.dump(ast.parse("""
... match x:
... case "Relevant":
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchValue(
value=Constant(value='Relevant')),
body=[
Expr(
value=Constant(value=Ellipsis))])])],
type_ignores=[])
class ast.MatchSingleton
(value)
A match literal pattern that compares by identity. value
is the singleton to be compared against: None
, True
, or False
. This pattern succeeds if the match subject is the given constant.
>>> print(ast.dump(ast.parse("""
... match x:
... case None:
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchSingleton(value=None),
body=[
Expr(
value=Constant(value=Ellipsis))])])],
type_ignores=[])
class ast.MatchSequence
(patterns)
A match sequence pattern. patterns
contains the patterns to be matched against the subject elements if the subject is a sequence. Matches a variable length sequence if one of the subpatterns is a MatchStar
node, otherwise matches a fixed length sequence.
>>> print(ast.dump(ast.parse("""
... match x:
... case [1, 2]:
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchSequence(
patterns=[
MatchValue(
value=Constant(value=1)),
MatchValue(
value=Constant(value=2))]),
body=[
Expr(
value=Constant(value=Ellipsis))])])],
type_ignores=[])
class ast.MatchStar
(name)
Matches the rest of the sequence in a variable length match sequence pattern. If name
is not None
, a list containing the remaining sequence elements is bound to that name if the overall sequence pattern is successful.
>>> print(ast.dump(ast.parse("""
... match x:
... case [1, 2, *rest]:
... ...
... case [*_]:
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchSequence(
patterns=[
MatchValue(
value=Constant(value=1)),
MatchValue(
value=Constant(value=2)),
MatchStar(name='rest')]),
body=[
Expr(
value=Constant(value=Ellipsis))]),
match_case(
pattern=MatchSequence(
patterns=[
MatchStar()]),
body=[
Expr(
value=Constant(value=Ellipsis))])])],
type_ignores=[])
class ast.MatchMapping
(keys, patterns, rest)
A match mapping pattern. keys
is a sequence of expression nodes. patterns
is a corresponding sequence of pattern nodes. rest
is an optional name that can be specified to capture the remaining mapping elements. Permitted key expressions are restricted as described in the match statement documentation.
This pattern succeeds if the subject is a mapping, all evaluated key expressions are present in the mapping, and the value corresponding to each key matches the corresponding subpattern. If rest
is not None
, a dict containing the remaining mapping elements is bound to that name if the overall mapping pattern is successful.
>>> print(ast.dump(ast.parse("""
... match x:
... case {1: _, 2: _}:
... ...
... case {**rest}:
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchMapping(
keys=[
Constant(value=1),
Constant(value=2)],
patterns=[
MatchAs(),
MatchAs()]),
body=[
Expr(
value=Constant(value=Ellipsis))]),
match_case(
pattern=MatchMapping(keys=[], patterns=[], rest='rest'),
body=[
Expr(
value=Constant(value=Ellipsis))])])],
type_ignores=[])
class ast.MatchClass
(cls, patterns, kwd_attrs, kwd_patterns)
A match class pattern. cls
is an expression giving the nominal class to be matched. patterns
is a sequence of pattern nodes to be matched against the class defined sequence of pattern matching attributes. kwd_attrs
is a sequence of additional attributes to be matched (specified as keyword arguments in the class pattern), kwd_patterns
are the corresponding patterns (specified as keyword values in the class pattern).
This pattern succeeds if the subject is an instance of the nominated class, all positional patterns match the corresponding class-defined attributes, and any specified keyword attributes match their corresponding pattern.
Note: classes may define a property that returns self in order to match a pattern node against the instance being matched. Several builtin types are also matched that way, as described in the match statement documentation.
>>> print(ast.dump(ast.parse("""
... match x:
... case Point2D(0, 0):
... ...
... case Point3D(x=0, y=0, z=0):
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchClass(
cls=Name(id='Point2D', ctx=Load()),
patterns=[
MatchValue(
value=Constant(value=0)),
MatchValue(
value=Constant(value=0))],
kwd_attrs=[],
kwd_patterns=[]),
body=[
Expr(
value=Constant(value=Ellipsis))]),
match_case(
pattern=MatchClass(
cls=Name(id='Point3D', ctx=Load()),
patterns=[],
kwd_attrs=[
'x',
'y',
'z'],
kwd_patterns=[
MatchValue(
value=Constant(value=0)),
MatchValue(
value=Constant(value=0)),
MatchValue(
value=Constant(value=0))]),
body=[
Expr(
value=Constant(value=Ellipsis))])])],
type_ignores=[])
class ast.MatchAs
(pattern, name)
A match “as-pattern”, capture pattern or wildcard pattern. pattern
contains the match pattern that the subject will be matched against. If the pattern is None
, the node represents a capture pattern (i.e a bare name) and will always succeed.
The name
attribute contains the name that will be bound if the pattern is successful. If name
is None
, pattern
must also be None
and the node represents the wildcard pattern.
>>> print(ast.dump(ast.parse("""
... match x:
... case [x] as y:
... ...
... case _:
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchAs(
pattern=MatchSequence(
patterns=[
MatchAs(name='x')]),
name='y'),
body=[
Expr(
value=Constant(value=Ellipsis))]),
match_case(
pattern=MatchAs(),
body=[
Expr(
value=Constant(value=Ellipsis))])])],
type_ignores=[])
class ast.MatchOr
(patterns)
A match “or-pattern”. An or-pattern matches each of its subpatterns in turn to the subject, until one succeeds. The or-pattern is then deemed to succeed. If none of the subpatterns succeed the or-pattern fails. The patterns
attribute contains a list of match pattern nodes that will be matched against the subject.
>>> print(ast.dump(ast.parse("""
... match x:
... case [x] | (y):
... ...
... """), indent=4))
Module(
body=[
Match(
subject=Name(id='x', ctx=Load()),
cases=[
match_case(
pattern=MatchOr(
patterns=[
MatchSequence(
patterns=[
MatchAs(name='x')]),
MatchAs(name='y')]),
body=[
Expr(
value=Constant(value=Ellipsis))])])],
type_ignores=[])
Function and class definitions
class ast.FunctionDef
(name, args, body, decorator_list, returns, type_comment)
A function definition.
name
is a raw string of the function name.args
is anarguments
node.body
is the list of nodes inside the function.decorator_list
is the list of decorators to be applied, stored outermost first (i.e. the first in the list will be applied last).returns
is the return annotation.type_comment
type_comment
is an optional string with the type annotation as a comment.
class ast.Lambda
(args, body)
lambda
is a minimal function definition that can be used inside an expression. Unlike FunctionDef
, body
holds a single node.
>>> print(ast.dump(ast.parse('lambda x,y: ...'), indent=4))
Module(
body=[
Expr(
value=Lambda(
args=arguments(
posonlyargs=[],
args=[
arg(arg='x'),
arg(arg='y')],
kwonlyargs=[],
kw_defaults=[],
defaults=[]),
body=Constant(value=Ellipsis)))],
type_ignores=[])
class ast.arguments
(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults)
The arguments for a function.
posonlyargs
,args
andkwonlyargs
are lists ofarg
nodes.vararg
andkwarg
are singlearg
nodes, referring to the*args, **kwargs
parameters.kw_defaults
is a list of default values for keyword-only arguments. If one isNone
, the corresponding argument is required.defaults
is a list of default values for arguments that can be passed positionally. If there are fewer defaults, they correspond to the last n arguments.
class ast.arg
(arg, annotation, type_comment)
A single argument in a list. arg
is a raw string of the argument name, annotation
is its annotation, such as a Str
or Name
node.
type_comment
type_comment
is an optional string with the type annotation as a comment
>>> print(ast.dump(ast.parse("""\
... @decorator1
... @decorator2
... def f(a: 'annotation', b=1, c=2, *d, e, f=3, **g) -> 'return annotation':
... pass
... """), indent=4))
Module(
body=[
FunctionDef(
name='f',
args=arguments(
posonlyargs=[],
args=[
arg(
arg='a',
annotation=Constant(value='annotation')),
arg(arg='b'),
arg(arg='c')],
vararg=arg(arg='d'),
kwonlyargs=[
arg(arg='e'),
arg(arg='f')],
kw_defaults=[
None,
Constant(value=3)],
kwarg=arg(arg='g'),
defaults=[
Constant(value=1),
Constant(value=2)]),
body=[
Pass()],
decorator_list=[
Name(id='decorator1', ctx=Load()),
Name(id='decorator2', ctx=Load())],
returns=Constant(value='return annotation'))],
type_ignores=[])
class ast.Return
(value)
A return
statement.
>>> print(ast.dump(ast.parse('return 4'), indent=4))
Module(
body=[
Return(
value=Constant(value=4))],
type_ignores=[])
class ast.Yield
(value)
class ast.YieldFrom
(value)
A yield
or yield from
expression. Because these are expressions, they must be wrapped in a Expr
node if the value sent back is not used.
>>> print(ast.dump(ast.parse('yield x'), indent=4))
Module(
body=[
Expr(
value=Yield(
value=Name(id='x', ctx=Load())))],
type_ignores=[])
>>> print(ast.dump(ast.parse('yield from x'), indent=4))
Module(
body=[
Expr(
value=YieldFrom(
value=Name(id='x', ctx=Load())))],
type_ignores=[])
class ast.Global
(names)
class ast.Nonlocal
(names)
global
and nonlocal
statements. names
is a list of raw strings.
>>> print(ast.dump(ast.parse('global x,y,z'), indent=4))
Module(
body=[
Global(
names=[
'x',
'y',
'z'])],
type_ignores=[])
>>> print(ast.dump(ast.parse('nonlocal x,y,z'), indent=4))
Module(
body=[
Nonlocal(
names=[
'x',
'y',
'z'])],
type_ignores=[])
class ast.ClassDef
(name, bases, keywords, starargs, kwargs, body, decorator_list)
A class definition.
name
is a raw string for the class namebases
is a list of nodes for explicitly specified base classes.keywords
is a list ofkeyword
nodes, principally for ‘metaclass’. Other keywords will be passed to the metaclass, as per PEP-3115.starargs
andkwargs
are each a single node, as in a function call. starargs will be expanded to join the list of base classes, and kwargs will be passed to the metaclass.body
is a list of nodes representing the code within the class definition.decorator_list
is a list of nodes, as inFunctionDef
.
>>> print(ast.dump(ast.parse("""\
... @decorator1
... @decorator2
... class Foo(base1, base2, metaclass=meta):
... pass
... """), indent=4))
Module(
body=[
ClassDef(
name='Foo',
bases=[
Name(id='base1', ctx=Load()),
Name(id='base2', ctx=Load())],
keywords=[
keyword(
arg='metaclass',
value=Name(id='meta', ctx=Load()))],
body=[
Pass()],
decorator_list=[
Name(id='decorator1', ctx=Load()),
Name(id='decorator2', ctx=Load())])],
type_ignores=[])
Async and await
class ast.AsyncFunctionDef
(name, args, body, decorator_list, returns, type_comment)
An async def
function definition. Has the same fields as FunctionDef
.
class ast.Await
(value)
An await
expression. value
is what it waits for. Only valid in the body of an AsyncFunctionDef
.
>>> print(ast.dump(ast.parse("""\
... async def f():
... await other_func()
... """), indent=4))
Module(
body=[
AsyncFunctionDef(
name='f',
args=arguments(
posonlyargs=[],
args=[],
kwonlyargs=[],
kw_defaults=[],
defaults=[]),
body=[
Expr(
value=Await(
value=Call(
func=Name(id='other_func', ctx=Load()),
args=[],
keywords=[])))],
decorator_list=[])],
type_ignores=[])
class ast.AsyncFor
(target, iter, body, orelse, type_comment)
class ast.AsyncWith
(items, body, type_comment)
async for
loops and async with
context managers. They have the same fields as For
and With
, respectively. Only valid in the body of an AsyncFunctionDef
.
注解
When a string is parsed by ast.parse()
, operator nodes (subclasses of ast.operator
, ast.unaryop
, ast.cmpop
, ast.boolop
and ast.expr_context
) on the returned tree will be singletons. Changes to one will be reflected in all other occurrences of the same value (e.g. ast.Add
).
ast
中的辅助函数
除了节点类, ast
模块里为遍历抽象语法树定义了这些工具函数和类:
ast.parse
(source, filename=’<unknown>’, mode=’exec’, **, type_comments=False, feature_version=None*)
把源码解析为AST节点。和 compile(source, filename, mode,ast.PyCF_ONLY_AST)
等价。
If type_comments=True
is given, the parser is modified to check and return type comments as specified by PEP 484 and PEP 526. This is equivalent to adding ast.PyCF_TYPE_COMMENTS
to the flags passed to compile()
. This will report syntax errors for misplaced type comments. Without this flag, type comments will be ignored, and the type_comment
field on selected AST nodes will always be None
. In addition, the locations of # type: ignore
comments will be returned as the type_ignores
attribute of Module
(otherwise it is always an empty list).
In addition, if mode
is 'func_type'
, the input syntax is modified to correspond to PEP 484 “signature type comments”, e.g. (str, int) -> List[str]
.
Also, setting feature_version
to a tuple (major, minor)
will attempt to parse using that Python version’s grammar. Currently major
must equal to 3
. For example, setting feature_version=(3, 4)
will allow the use of async
and await
as variable names. The lowest supported version is (3, 4)
; the highest is sys.version_info[0:2]
.
If source contains a null character (‘0’), ValueError
is raised.
警告
Note that succesfully parsing souce code into an AST object doesn’t guarantee that the source code provided is valid Python code that can be executed as the compilation step can raise further
SyntaxError
exceptions. For instance, the sourcereturn 42
generates a valid AST node for a return statement, but it cannot be compiled alone (it needs to be inside a function node).In particular,
ast.parse()
won’t do any scoping checks, which the compilation step does.
警告
足够复杂或是巨大的字符串可能导致Python解释器的崩溃,因为Python的AST编译器是有栈深限制的。
在 3.8 版更改: Added type_comments
, mode='func_type'
and feature_version
.
ast.unparse
(ast_obj)
Unparse an ast.AST
object and generate a string with code that would produce an equivalent ast.AST
object if parsed back with ast.parse()
.
警告
The produced code string will not necessarily be equal to the original code that generated the ast.AST
object (without any compiler optimizations, such as constant tuples/frozensets).
警告
Trying to unparse a highly complex expression would result with RecursionError
.
3.9 新版功能.
ast.literal_eval
(node_or_string)
Safely evaluate an expression node or a string containing a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, None
and Ellipsis
.
This can be used for safely evaluating strings containing Python values from untrusted sources without the need to parse the values oneself. It is not capable of evaluating arbitrarily complex expressions, for example involving operators or indexing.
警告
足够复杂或是巨大的字符串可能导致Python解释器的崩溃,因为Python的AST编译器是有栈深限制的。
It can raise ValueError
, TypeError
, SyntaxError
, MemoryError
and RecursionError
depending on the malformed input.
在 3.2 版更改: 目前支持字节和集合。
在 3.9 版更改: Now supports creating empty sets with 'set()'
.
在 3.10 版更改: For string inputs, leading spaces and tabs are now stripped.
ast.get_docstring
(node, clean=True)
Return the docstring of the given node (which must be a FunctionDef
, AsyncFunctionDef
, ClassDef
, or Module
node), or None
if it has no docstring. If clean is true, clean up the docstring’s indentation with inspect.cleandoc()
.
在 3.5 版更改: 目前支持 AsyncFunctionDef
ast.get_source_segment
(source, node, **, padded=False*)
Get source code segment of the source that generated node. If some location information (lineno
, end_lineno
, col_offset
, or end_col_offset
) is missing, return None
.
If padded is True
, the first line of a multi-line statement will be padded with spaces to match its original position.
3.8 新版功能.
ast.fix_missing_locations
(node)
When you compile a node tree with compile()
, the compiler expects lineno
and col_offset
attributes for every node that supports them. This is rather tedious to fill in for generated nodes, so this helper adds these attributes recursively where not already set, by setting them to the values of the parent node. It works recursively starting at node.
ast.increment_lineno
(node, n=1)
Increment the line number and end line number of each node in the tree starting at node by n. This is useful to “move code” to a different location in a file.
ast.copy_location
(new_node, old_node)
Copy source location (lineno
, col_offset
, end_lineno
, and end_col_offset
) from old_node to new_node if possible, and return new_node.
ast.iter_fields
(node)
Yield a tuple of (fieldname, value)
for each field in node._fields
that is present on node.
ast.iter_child_nodes
(node)
Yield all direct child nodes of node, that is, all fields that are nodes and all items of fields that are lists of nodes.
ast.walk
(node)
Recursively yield all descendant nodes in the tree starting at node (including node itself), in no specified order. This is useful if you only want to modify nodes in place and don’t care about the context.
class ast.NodeVisitor
A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit()
method.
This class is meant to be subclassed, with the subclass adding visitor methods.
visit
(node)Visit a node. The default implementation calls the method called
self.visit_*classname*
where classname is the name of the node class, orgeneric_visit()
if that method doesn’t exist.generic_visit
(node)This visitor calls
visit()
on all children of the node.Note that child nodes of nodes that have a custom visitor method won’t be visited unless the visitor calls
generic_visit()
or visits them itself.
Don’t use the NodeVisitor
if you want to apply changes to nodes during traversal. For this a special visitor exists (NodeTransformer
) that allows modifications.
3.8 版后已移除: Methods visit_Num()
, visit_Str()
, visit_Bytes()
, visit_NameConstant()
and visit_Ellipsis()
are deprecated now and will not be called in future Python versions. Add the visit_Constant()
method to handle all constant nodes.
class ast.NodeTransformer
子类 NodeVisitor
用于遍历抽象语法树,并允许修改节点。
NodeTransformer
将遍历抽象语法树并使用visitor方法的返回值去替换或移除旧节点。如果visitor方法的返回值为 None
, 则该节点将从其位置移除,否则将替换为返回值。当返回值是原始节点时,无需替换。
如下是一个转换器示例,它将所有出现的名称 (foo
) 重写为 data['foo']
:
class RewriteName(NodeTransformer):
def visit_Name(self, node):
return Subscript(
value=Name(id='data', ctx=Load()),
slice=Constant(value=node.id),
ctx=node.ctx
)
请记住,如果您正在操作的节点具有子节点,则必须先转换其子节点或为该节点调用 generic_visit()
方法。
对于属于语句集合(适用于所有语句节点)的节点,访问者还可以返回节点列表而不仅仅是单个节点。
If NodeTransformer
introduces new nodes (that weren’t part of original tree) without giving them location information (such as lineno
), fix_missing_locations()
should be called with the new sub-tree to recalculate the location information:
tree = ast.parse('foo', mode='eval')
new_tree = fix_missing_locations(RewriteName().visit(tree))
通常你可以像这样使用转换器:
node = YourTransformer().visit(node)
ast.dump
(node, annotate_fields=True, include_attributes=False, **, indent=None*)
Return a formatted dump of the tree in node. This is mainly useful for debugging purposes. If annotate_fields is true (by default), the returned string will show the names and the values for fields. If annotate_fields is false, the result string will be more compact by omitting unambiguous field names. Attributes such as line numbers and column offsets are not dumped by default. If this is wanted, include_attributes can be set to true.
If indent is a non-negative integer or string, then the tree will be pretty-printed with that indent level. An indent level of 0, negative, or ""
will only insert newlines. None
(the default) selects the single line representation. Using a positive integer indent indents that many spaces per level. If indent is a string (such as "\t"
), that string is used to indent each level.
在 3.9 版更改: Added the indent option.
Compiler Flags
The following flags may be passed to compile()
in order to change effects on the compilation of a program:
ast.PyCF_ALLOW_TOP_LEVEL_AWAIT
Enables support for top-level await
, async for
, async with
and async comprehensions.
3.8 新版功能.
ast.PyCF_ONLY_AST
Generates and returns an abstract syntax tree instead of returning a compiled code object.
ast.PyCF_TYPE_COMMENTS
Enables support for PEP 484 and PEP 526 style type comments (# type: <type>
, # type: ignore <stuff>
).
3.8 新版功能.
Command-Line Usage
3.9 新版功能.
The ast
module can be executed as a script from the command line. It is as simple as:
python -m ast [-m <mode>] [-a] [infile]
The following options are accepted:
-h``,` `--help
Show the help message and exit.
-m` `<mode>
--mode` `<mode>
Specify what kind of code must be compiled, like the mode argument in parse()
.
--no-type-comments
Don’t parse type comments.
-a``,` `--include-attributes
Include attributes such as line numbers and column offsets.
-i` `<indent>
--indent` `<indent>
Indentation of nodes in AST (number of spaces).
If infile
is specified its contents are parsed to AST and dumped to stdout. Otherwise, the content is read from stdin.
参见
Green Tree Snakes, an external documentation resource, has good details on working with Python ASTs.
ASTTokens annotates Python ASTs with the positions of tokens and text in the source code that generated them. This is helpful for tools that make source code transformations.
leoAst.py unifies the token-based and parse-tree-based views of python programs by inserting two-way links between tokens and ast nodes.
LibCST parses code as a Concrete Syntax Tree that looks like an ast tree and keeps all formatting details. It’s useful for building automated refactoring (codemod) applications and linters.
Parso is a Python parser that supports error recovery and round-trip parsing for different Python versions (in multiple Python versions). Parso is also able to list multiple syntax errors in your python file.
symtable
—- Access to the compiler’s symbol tables
Source code: Lib/symtable.py
Symbol tables are generated by the compiler from AST just before bytecode is generated. The symbol table is responsible for calculating the scope of every identifier in the code. symtable
provides an interface to examine these tables.
Generating Symbol Tables
symtable.symtable
(code, filename, compile_type)
Return the toplevel SymbolTable
for the Python source code. filename is the name of the file containing the code. compile_type is like the mode argument to compile()
.
Examining Symbol Tables
class symtable.SymbolTable
A namespace table for a block. The constructor is not public.
get_type
()Return the type of the symbol table. Possible values are
'class'
,'module'
, and'function'
.get_id
()Return the table’s identifier.
get_name
()Return the table’s name. This is the name of the class if the table is for a class, the name of the function if the table is for a function, or
'top'
if the table is global (get_type()
returns'module'
).get_lineno
()Return the number of the first line in the block this table represents.
is_optimized
()Return
True
if the locals in this table can be optimized.is_nested
()Return
True
if the block is a nested class or function.has_children
()Return
True
if the block has nested namespaces within it. These can be obtained withget_children()
.get_identifiers
()Return a list of names of symbols in this table.
lookup
(name)Lookup name in the table and return a
Symbol
instance.get_symbols
()Return a list of
Symbol
instances for names in the table.get_children
()Return a list of the nested symbol tables.
class symtable.Function
A namespace for a function or method. This class inherits SymbolTable
.
get_parameters
()Return a tuple containing names of parameters to this function.
get_locals
()Return a tuple containing names of locals in this function.
get_globals
()Return a tuple containing names of globals in this function.
get_nonlocals
()Return a tuple containing names of nonlocals in this function.
get_frees
()Return a tuple containing names of free variables in this function.
class symtable.Class
A namespace of a class. This class inherits SymbolTable
.
get_methods
()Return a tuple containing the names of methods declared in the class.
class symtable.Symbol
An entry in a SymbolTable
corresponding to an identifier in the source. The constructor is not public.
get_name
()Return the symbol’s name.
is_referenced
()Return
True
if the symbol is used in its block.is_imported
()Return
True
if the symbol is created from an import statement.is_parameter
()Return
True
if the symbol is a parameter.is_global
()Return
True
if the symbol is global.is_nonlocal
()Return
True
if the symbol is nonlocal.is_declared_global
()Return
True
if the symbol is declared global with a global statement.is_local
()Return
True
if the symbol is local to its block.is_annotated
()Return
True
if the symbol is annotated.3.6 新版功能.
is_free
()Return
True
if the symbol is referenced in its block, but not assigned to.is_assigned
()Return
True
if the symbol is assigned to in its block.is_namespace
()Return
True
if name binding introduces new namespace.If the name is used as the target of a function or class statement, this will be true.
例如:
>>> table = symtable.symtable("def some_func(): pass", "string", "exec") >>> table.lookup("some_func").is_namespace() True
Note that a single name can be bound to multiple objects. If the result is
True
, the name may also be bound to other objects, like an int or list, that does not introduce a new namespace.get_namespaces
()Return a list of namespaces bound to this name.
get_namespace
()Return the namespace bound to this name. If more than one namespace is bound,
ValueError
is raised.
token
—- 与Python解析树一起使用的常量
源码: Lib/token.py
This module provides constants which represent the numeric values of leaf nodes of the parse tree (terminal tokens). Refer to the file Grammar/Tokens
in the Python distribution for the definitions of the names in the context of the language grammar. The specific numeric values which the names map to may change between Python versions.
该模块还提供从数字代码到名称和一些函数的映射。 这些函数镜像了 Python C 头文件中的定义。
token.tok_name
将此模块中定义的常量的数值映射回名称字符串的字典,允许生成更加人类可读的解析树表示。
token.ISTERMINAL
(x)
对终端标记值返回 True
。
token.ISNONTERMINAL
(x)
对非终端标记值返回 True
。
token.ISEOF
(x)
如果 x 是表示输入结束的标记则返回 True
。
标记常量是:
token.ENDMARKER
token.NAME
token.NUMBER
token.STRING
token.NEWLINE
token.INDENT
token.DEDENT
token.LPAR
"("
的权标值。
token.RPAR
")"
的权标值。
token.LSQB
"["
的权标值。
token.RSQB
"]"
的权标值。
token.COLON
":"
的权标值。
token.COMMA
","
的权标值。
token.SEMI
";"
的权标值。
token.PLUS
"+"
的权标值。
token.MINUS
"-"
的权标值。
token.STAR
"*"
的权标值。
token.SLASH
"/"
的权标值。
token.VBAR
"|"
的权标值。
token.AMPER
"&"
的权标值。
token.LESS
"<"
的权标值。
token.GREATER
">"
的权标值。
token.EQUAL
Token value for "="
.
token.DOT
Token value for "."
.
token.PERCENT
Token value for "%"
.
token.LBRACE
Token value for "{"
.
token.RBRACE
Token value for "}"
.
token.EQEQUAL
Token value for "=="
.
token.NOTEQUAL
Token value for "!="
.
token.LESSEQUAL
Token value for "<="
.
token.GREATEREQUAL
Token value for ">="
.
token.TILDE
Token value for "~"
.
token.CIRCUMFLEX
Token value for "^"
.
token.LEFTSHIFT
Token value for "<<"
.
token.RIGHTSHIFT
Token value for ">>"
.
token.DOUBLESTAR
Token value for "**"
.
token.PLUSEQUAL
Token value for "+="
.
token.MINEQUAL
Token value for "-="
.
token.STAREQUAL
Token value for "*="
.
token.SLASHEQUAL
Token value for "/="
.
token.PERCENTEQUAL
Token value for "%="
.
token.AMPEREQUAL
Token value for "&="
.
token.VBAREQUAL
Token value for "|="
.
token.CIRCUMFLEXEQUAL
Token value for "^="
.
token.LEFTSHIFTEQUAL
Token value for "<<="
.
token.RIGHTSHIFTEQUAL
Token value for ">>="
.
token.DOUBLESTAREQUAL
Token value for "**="
.
token.DOUBLESLASH
Token value for "//"
.
token.DOUBLESLASHEQUAL
Token value for "//="
.
token.AT
Token value for "@"
.
token.ATEQUAL
Token value for "@="
.
token.RARROW
Token value for "->"
.
token.ELLIPSIS
Token value for "..."
.
token.COLONEQUAL
Token value for ":="
.
token.OP
token.AWAIT
token.ASYNC
token.TYPE_IGNORE
token.TYPE_COMMENT
token.SOFT_KEYWORD
token.ERRORTOKEN
token.N_TOKENS
token.NT_OFFSET
C 标记生成器不使用以下标记类型值,但 tokenize
模块需要这些标记类型值。
token.COMMENT
标记值用于表示注释。
token.NL
标记值用于表示非终止换行符。 NEWLINE
标记表示 Python 代码逻辑行的结束;当在多条物理线路上继续执行逻辑代码行时,会生成 NL
标记。
token.ENCODING
指示用于将源字节解码为文本的编码的标记值。 tokenize.tokenize()
返回的第一个标记将始终是一个 ENCODING
标记。
token.TYPE_COMMENT
Token value indicating that a type comment was recognized. Such tokens are only produced when ast.parse()
is invoked with type_comments=True
.
在 3.5 版更改: 补充 AWAIT
和 ASYNC
标记。
在 3.7 版更改: 补充 COMMENT
、 NL
和 ENCODING
标记。
在 3.7 版更改: 移除 AWAIT
和 ASYNC
标记。 “async” 和 “await” 现在被标记为 NAME
标记。
在 3.8 版更改: Added TYPE_COMMENT
, TYPE_IGNORE
, COLONEQUAL
. Added AWAIT
and ASYNC
tokens back (they’re needed to support parsing older Python versions for ast.parse()
with feature_version
set to 6 or lower).
keyword
—- 检验Python关键字
源码: Lib/keyword.py
此模块允许 Python 程序确定某个字符串是否为 关键字。
keyword.iskeyword
(s)
如果 s 是一个 Python 关键字 则返回 True
。
keyword.kwlist
包含解释器定义的所有 关键字 的序列。 如果所定义的任何关键字仅在特定 __future__
语句生效时被激活,它们也将被包含在内。
keyword.issoftkeyword
(s)
如果 s 是一个 Python 的软 关键字 则返回 True
。
3.9 新版功能.
keyword.softkwlist
包含解释器定义的所有软 关键字 的序列。 如果所定义的任何软关键字仅在特定 __future__
语句生效时被激活,它们也将被包含在内。
3.9 新版功能.
tokenize
—- 对 Python 代码使用的标记解析器
源码: Lib/tokenize.py
The tokenize
module provides a lexical scanner for Python source code, implemented in Python. The scanner in this module returns comments as tokens as well, making it useful for implementing “pretty-printers”, including colorizers for on-screen displays.
为了简化标记流的处理,所有的 运算符 和 定界符 以及 Ellipsis
返回时都会打上通用的 OP
标记。 可以通过 tokenize.tokenize()
返回的 named tuple 对象的 exact_type
属性来获得确切的标记类型。
对输入进行解析标记
主要的入口是一个 generator:
tokenize.tokenize
(readline)
生成器 tokenize()
需要一个 readline 参数,这个参数必须是一个可调用对象,且能提供与文件对象的 io.IOBase.readline()
方法相同的接口。每次调用这个函数都要 返回字节类型输入的一行数据。
The generator produces 5-tuples with these members: the token type; the token string; a 2-tuple (srow, scol)
of ints specifying the row and column where the token begins in the source; a 2-tuple (erow, ecol)
of ints specifying the row and column where the token ends in the source; and the line on which the token was found. The line passed (the last tuple item) is the physical line. The 5 tuple is returned as a named tuple with the field names: type string start end line
.
The returned named tuple has an additional property named exact_type
that contains the exact operator type for OP
tokens. For all other token types exact_type
equals the named tuple type
field.
在 3.1 版更改: Added support for named tuples.
在 3.3 版更改: Added support for exact_type
.
tokenize()
determines the source encoding of the file by looking for a UTF-8 BOM or encoding cookie, according to PEP 263.
tokenize.generate_tokens
(readline)
Tokenize a source reading unicode strings instead of bytes.
Like tokenize()
, the readline argument is a callable returning a single line of input. However, generate_tokens()
expects readline to return a str object rather than bytes.
The result is an iterator yielding named tuples, exactly like tokenize()
. It does not yield an ENCODING
token.
All constants from the token
module are also exported from tokenize
.
Another function is provided to reverse the tokenization process. This is useful for creating tools that tokenize a script, modify the token stream, and write back the modified script.
tokenize.untokenize
(iterable)
Converts tokens back into Python source code. The iterable must return sequences with at least two elements, the token type and the token string. Any additional sequence elements are ignored.
The reconstructed script is returned as a single string. The result is guaranteed to tokenize back to match the input so that the conversion is lossless and round-trips are assured. The guarantee applies only to the token type and token string as the spacing between tokens (column positions) may change.
It returns bytes, encoded using the ENCODING
token, which is the first token sequence output by tokenize()
. If there is no encoding token in the input, it returns a str instead.
tokenize()
needs to detect the encoding of source files it tokenizes. The function it uses to do this is available:
tokenize.detect_encoding
(readline)
The detect_encoding()
function is used to detect the encoding that should be used to decode a Python source file. It requires one argument, readline, in the same way as the tokenize()
generator.
It will call readline a maximum of twice, and return the encoding used (as a string) and a list of any lines (not decoded from bytes) it has read in.
It detects the encoding from the presence of a UTF-8 BOM or an encoding cookie as specified in PEP 263. If both a BOM and a cookie are present, but disagree, a SyntaxError
will be raised. Note that if the BOM is found, 'utf-8-sig'
will be returned as an encoding.
If no encoding is specified, then the default of 'utf-8'
will be returned.
Use open()
to open Python source files: it uses detect_encoding()
to detect the file encoding.
tokenize.open
(filename)
Open a file in read only mode using the encoding detected by detect_encoding()
.
3.2 新版功能.
exception tokenize.TokenError
Raised when either a docstring or expression that may be split over several lines is not completed anywhere in the file, for example:
"""Beginning of
docstring
或者:
[1,
2,
3
Note that unclosed single-quoted strings do not cause an error to be raised. They are tokenized as ERRORTOKEN
, followed by the tokenization of their contents.
Command-Line Usage
3.3 新版功能.
The tokenize
module can be executed as a script from the command line. It is as simple as:
python -m tokenize [-e] [filename.py]
The following options are accepted:
-h``,` `--help
show this help message and exit
-e``,` `--exact
display token names using the exact type
If filename.py
is specified its contents are tokenized to stdout. Otherwise, tokenization is performed on stdin.
例子
Example of a script rewriter that transforms float literals into Decimal objects:
from tokenize import tokenize, untokenize, NUMBER, STRING, NAME, OP
from io import BytesIO
def decistmt(s):
"""Substitute Decimals for floats in a string of statements.
>>> from decimal import Decimal
>>> s = 'print(+21.3e-5*-.1234/81.7)'
>>> decistmt(s)
"print (+Decimal ('21.3e-5')*-Decimal ('.1234')/Decimal ('81.7'))"
The format of the exponent is inherited from the platform C library.
Known cases are "e-007" (Windows) and "e-07" (not Windows). Since
we're only showing 12 digits, and the 13th isn't close to 5, the
rest of the output should be platform-independent.
>>> exec(s) #doctest: +ELLIPSIS
-3.21716034272e-0...7
Output from calculations with Decimal should be identical across all
platforms.
>>> exec(decistmt(s))
-3.217160342717258261933904529E-7
"""
result = []
g = tokenize(BytesIO(s.encode('utf-8')).readline) # tokenize the string
for toknum, tokval, _, _, _ in g:
if toknum == NUMBER and '.' in tokval: # replace NUMBER tokens
result.extend([
(NAME, 'Decimal'),
(OP, '('),
(STRING, repr(tokval)),
(OP, ')')
])
else:
result.append((toknum, tokval))
return untokenize(result).decode('utf-8')
Example of tokenizing from the command line. The script:
def say_hello():
print("Hello, World!")
say_hello()
will be tokenized to the following output where the first column is the range of the line/column coordinates where the token is found, the second column is the name of the token, and the final column is the value of the token (if any)
$ python -m tokenize hello.py
0,0-0,0: ENCODING 'utf-8'
1,0-1,3: NAME 'def'
1,4-1,13: NAME 'say_hello'
1,13-1,14: OP '('
1,14-1,15: OP ')'
1,15-1,16: OP ':'
1,16-1,17: NEWLINE '\n'
2,0-2,4: INDENT ' '
2,4-2,9: NAME 'print'
2,9-2,10: OP '('
2,10-2,25: STRING '"Hello, World!"'
2,25-2,26: OP ')'
2,26-2,27: NEWLINE '\n'
3,0-3,1: NL '\n'
4,0-4,0: DEDENT ''
4,0-4,9: NAME 'say_hello'
4,9-4,10: OP '('
4,10-4,11: OP ')'
4,11-4,12: NEWLINE '\n'
5,0-5,0: ENDMARKER ''
The exact token type names can be displayed using the -e
option:
$ python -m tokenize -e hello.py
0,0-0,0: ENCODING 'utf-8'
1,0-1,3: NAME 'def'
1,4-1,13: NAME 'say_hello'
1,13-1,14: LPAR '('
1,14-1,15: RPAR ')'
1,15-1,16: COLON ':'
1,16-1,17: NEWLINE '\n'
2,0-2,4: INDENT ' '
2,4-2,9: NAME 'print'
2,9-2,10: LPAR '('
2,10-2,25: STRING '"Hello, World!"'
2,25-2,26: RPAR ')'
2,26-2,27: NEWLINE '\n'
3,0-3,1: NL '\n'
4,0-4,0: DEDENT ''
4,0-4,9: NAME 'say_hello'
4,9-4,10: LPAR '('
4,10-4,11: RPAR ')'
4,11-4,12: NEWLINE '\n'
5,0-5,0: ENDMARKER ''
Example of tokenizing a file programmatically, reading unicode strings instead of bytes with generate_tokens()
:
import tokenize
with tokenize.open('hello.py') as f:
tokens = tokenize.generate_tokens(f.readline)
for token in tokens:
print(token)
或者通过 tokenize()
直接读取字节数据:
import tokenize
with open('hello.py', 'rb') as f:
tokens = tokenize.tokenize(f.readline)
for token in tokens:
print(token)
tabnanny
—- 模糊缩进检测
源代码: Lib/tabnanny.py
目前,该模块旨在作为脚本调用。但是可以使用下面描述的 check()
函数将其导入IDE。
注解
此模块提供的API可能会在将来的版本中更改;此类更改可能无法向后兼容。
tabnanny.check
(file_or_dir)
如果 file_or_dir 是目录而非符号链接,则递归地在名为 file_or_dir 的目录树中下行,沿途检查所有 .py
文件。 如果 file_or_dir 是一个普通 Python 源文件,将检查其中的空格相关问题。 诊断消息将使用 print()
函数写入到标准输出。
tabnanny.verbose
此旗标指明是否打印详细消息。 如果作为脚本调用则是通过 -v
选项来增加。
tabnanny.filename_only
此旗标指明是否只打印包含空格相关问题文件的文件名。 如果作为脚本调用则是通过 -q
选项来设为真值。
exception tabnanny.NannyNag
如果检测到模糊缩进则由 process_tokens()
引发。 在 check()
中捕获并处理。
tabnanny.process_tokens
(tokens)
此函数由 check()
用来处理由 tokenize
模块所生成的标记。
pyclbr
—- Python 模块浏览器支持
源代码: Lib/pyclbr.py
pyclbr
模块提供了对于以 Python 编写的模块中定义的函数、类和方法的受限信息。 这种信息足够用来实现一个模块浏览器。 这种信息是从 Python 源代码中直接提取而非通过导入模块,因此该模块可以安全地用于不受信任的代码。 此限制使得非 Python 实现的模块无法使用此模块,包括所有标准和可选的扩展模块。
pyclbr.readmodule
(module, path=None)
返回一个将模块层级的类名映射到类描述器的字典。 如果可能,将会包括已导入基类的描述器。 形参 module 为要读取模块名称的字符串;它可能是某个包内部的模块名称。 path 如果给出则为添加到 sys.path
开头的目录路径序列,它会被用于定位模块的源代码。
此函数为原始接口,仅保留用于向下兼容。 它会返回以下内容的过滤版本。
pyclbr.readmodule_ex
(module, path=None)
返回一个基于字典的树,其中包含与模块中每个用 def
或 class
语句定义的函数和类相对应的函数和类描述器。 被返回的字典会将模块层级的函数和类名映射到它们的描述器。 嵌套的对象会被输入到它们的上级子目录中。 与 readmodule 一样,module 指明要读取的模块而 path 会被添加到 sys.path。 如果被读取的模块是一个包,则返回的字典将具有 '__path__'
键,其值是一个包含包搜索路径的列表。
3.7 新版功能: 嵌套定义的描述器。 它们通过新的子属性来访问。 每个定义都会有一个新的上级属性。
这些函数所返回的描述器是 Function 和 Class 类的实例。 用户不应自行创建这些类的实例。
Function 对象
Function
类的实例描述了由 def 语句所定义的函数。 它们具有下列属性:
Function.file
函数定义所在的文件名称。
Function.module
定义了所描述函数的模块名称。
Function.name
函数名称。
Function.lineno
定义在文件中起始位置的行号。
Function.parent
对于最高层级函数为 None。 对于嵌套函数则为上级函数。
3.7 新版功能.
Function.children
将名称映射到嵌套函数和类描述器的字典。
3.7 新版功能.
Function.is_async
True
针对使用 async
前缀定义的函数,其他情况下为 False
。
3.10 新版功能.
Class 对象
Class
类的实例描述了由 class 语句所定义的类。 它们具有与 Function 对象相同的属性以及两个额外属性。
Class.file
类定义所在的文件名称。
Class.module
定义了所描述类的模块名称。
Class.name
类名称。
Class.lineno
定义在文件中起始位置的行号。
Class.parent
对于最高层级类为 None。 对于嵌套类则为上级类。
3.7 新版功能.
Class.children
将名称映射到嵌套函数和类描述器的字典。
3.7 新版功能.
Class.super
一个 Class
对象的列表,它们描述了所描述类的直接基类。 被命名为超类但无法被 readmodule_ex()
发现的类会作为类名字符串而非 Class
对象列出。
Class.methods
一个将方法名映射到行号的字典。 此属性可从更新的子目录中获取,仅保留用于向下兼容。
py_compile
—- 编译 Python 源文件
源代码: Lib/py_compile.py
py_compile
模块提供了用来从源文件生成字节码的函数和另一个用于当模块源文件作为脚本被调用时的函数。
虽然不太常用,但这个函数在安装共享模块时还是很有用的,特别是当一些用户可能没有权限在包含源代码的目录中写字节码缓存文件时。
exception py_compile.PyCompileError
当编译文件过程中发生错误时,抛出的异常。
py_compile.compile
(file, cfile=None, dfile=None, doraise=False, optimize=- 1, invalidation_mode=PycInvalidationMode.TIMESTAMP, quiet=0)
将源文件编译成字节码并写出字节码缓存文件。 源代码从名为 file 的文件中加载。 字节码会写入到 cfile,默认为 [*PEP 3147](https://www.python.org/dev/peps/pep-3147)/[PEP 488**](https://www.python.org/dev/peps/pep-0488) 路径,以 .pyc
结尾。 例如,如果 *file 是 /foo/bar/baz.py
则对于 Python 3.2 cfile 将默认为 /foo/bar/__pycache__/baz.cpython-32.pyc
。 如果指定了 dfile*,则在错误信息中它将代替 *file 作为源文件的名称。 如果 doraise 为真值,则当编译 file 遇到错误时将会引发 PyCompileError
。 如果 doraise 为假值(默认),则将错误信息写入到 sys.stderr
,但不会引发异常。 此函数返回编译后字节码文件的路径,即 cfile 所使用的值。
doraise 和 quiet 参数确定在编译文件时如何处理错误。 如果 quiet 为 0 或 1,并且 doraise 为假值,则会启用默认行为:写入错误信息到 sys.stderr
,并且函数将返回 None
而非一个路径。 如果 doraise 为真值,则将改为引发 PyCompileError
。 但是如果 quiet 为 2,则不会写入消息,并且 doraise 也不会有效果。
如果 cfile 所表示(显式指定或计算得出)的路径为符号链接或非常规文件,则将引发 FileExistsError
。 此行为是用来警告如果允许写入编译后字节码文件到这些路径则导入操作将会把它们转为常规文件。 这是使用文件重命名来将最终编译后字节码文件放置到位以防止并发文件写入问题的导入操作的附带效果。
optimize 控制优化级别并会被传给内置的 compile()
函数。 默认值 -1
表示选择当前解释器的优化级别。
invalidation_mode 应当是 PycInvalidationMode
枚举的成员,它控制在运行时如何让已生成的字节码缓存失效。 如果设置了 SOURCE_DATE_EPOCH
环境变量则默认值为 PycInvalidationMode.CHECKED_HASH
,否则默认值为 PycInvalidationMode.TIMESTAMP
。
在 3.2 版更改: 将 cfile 的默认值改成与 PEP 3147 兼容。 之前的默认值是 file + 'c'
(如果启用优化则为 'o'
)。 同时也添加了 optimize 形参。
在 3.4 版更改: 将代码更改为使用 importlib
执行字节码缓存文件写入。 这意味着文件创建/写入的语义现在与 importlib
所做的相匹配,例如权限、写入和移动语义等等。 同时也添加了当 cfile 为符号链接或非常规文件时引发 FileExistsError
的预警设置。
在 3.7 版更改: invalidation_mode 形参是根据 PEP 552 的描述添加的。 如果设置了 SOURCE_DATE_EPOCH
环境变量,invalidation_mode 将被强制设为 PycInvalidationMode.CHECKED_HASH
。
在 3.7.2 版更改: SOURCE_DATE_EPOCH
环境变量不会再覆盖 invalidation_mode 参数的值,而改为确定其默认值。
在 3.8 版更改: 增加了 quiet 形参。
class py_compile.PycInvalidationMode
一个由可用方法组成的枚举,解释器可以用来确定字节码文件是否与源文件保持一致。 .pyc
文件在其标头中指明了所需的失效模式。 Python 在运行时如何让 .pyc
文件失效的更多信息。
3.7 新版功能.
TIMESTAMP
.pyc
文件包括时间戳和源文件的大小,Python 将在运行时将其与源文件的元数据进行比较以确定.pyc
文件是否需要重新生成。CHECKED_HASH
.pyc
文件包括源文件内容的哈希值,Python 将在运行时将其与源文件内容进行比较以确定.pyc
文件是否需要重新生成。UNCHECKED_HASH
类似于
CHECKED_HASH
,.pyc
文件包括源文件内容的哈希值。 但是,Python 将在运行时假定.pyc
文件是最新的而完全不会将.pyc
与源文件进行验证。此选项适用于
.pycs
由 Python 以外的某个系统例如构建系统来确保最新的情况。
命令行接口
这个模块可作为脚本发起调用以编译多个源文件。 在 filenames 中指定的文件会被编译并将结果字节码以普通方式进行缓存。 这个程序不会搜索目录结构来定位源文件;它只编译显式指定的文件。 如果某个文件无法被编译则退出状态为非零值。
<file>` `... <fileN>
-
位置参数是要编译的文件。 如果 -
是唯一的形参,则文件列表将从标准输入获取。
-q``,` `--quiet
屏蔽错误输出。
在 3.2 版更改: 添加了对 -
的支持。
在 3.10 版更改: 添加了对 -q
的支持。
compileall
—- Byte-compile Python libraries
Source code: Lib/compileall.py
This module provides some utility functions to support installing Python libraries. These functions compile Python source files in a directory tree. This module can be used to create the cached byte-code files at library installation time, which makes them available for use even by users who don’t have write permission to the library directories.
Command-line use
This module can work as a script (using python -m compileall) to compile Python sources.
directory` `...
file` `...
Positional arguments are files to compile or directories that contain source files, traversed recursively. If no argument is given, behave as if the command line was -l <directories from sys.path>
.
-l
Do not recurse into subdirectories, only compile source code files directly contained in the named or implied directories.
-f
Force rebuild even if timestamps are up-to-date.
-q
Do not print the list of files compiled. If passed once, error messages will still be printed. If passed twice (-qq
), all output is suppressed.
-d` `destdir
Directory prepended to the path to each file being compiled. This will appear in compilation time tracebacks, and is also compiled in to the byte-code file, where it will be used in tracebacks and other messages in cases where the source file does not exist at the time the byte-code file is executed.
-s` `strip_prefix
-p` `prepend_prefix
Remove (-s
) or append (-p
) the given prefix of paths recorded in the .pyc
files. Cannot be combined with -d
.
-x` `regex
regex is used to search the full path to each file considered for compilation, and if the regex produces a match, the file is skipped.
-i` `list
Read the file list
and add each line that it contains to the list of files and directories to compile. If list
is -
, read lines from stdin
.
-b
Write the byte-code files to their legacy locations and names, which may overwrite byte-code files created by another version of Python. The default is to write files to their PEP 3147 locations and names, which allows byte-code files from multiple versions of Python to coexist.
-r
Control the maximum recursion level for subdirectories. If this is given, then -l
option will not be taken into account. python -m compileall <directory> -r 0 is equivalent to python -m compileall <directory> -l.
-j` `N
Use N workers to compile the files within the given directory. If 0
is used, then the result of os.cpu_count()
will be used.
--invalidation-mode` `[timestamp|checked-hash|unchecked-hash]
Control how the generated byte-code files are invalidated at runtime. The timestamp
value, means that .pyc
files with the source timestamp and size embedded will be generated. The checked-hash
and unchecked-hash
values cause hash-based pycs to be generated. Hash-based pycs embed a hash of the source file contents rather than a timestamp. See 已缓存字节码的失效 for more information on how Python validates bytecode cache files at runtime. The default is timestamp
if the SOURCE_DATE_EPOCH
environment variable is not set, and checked-hash
if the SOURCE_DATE_EPOCH
environment variable is set.
-o` `level
Compile with the given optimization level. May be used multiple times to compile for multiple levels at a time (for example, compileall -o 1 -o 2
).
-e` `dir
Ignore symlinks pointing outside the given directory.
--hardlink-dupes
If two .pyc
files with different optimization level have the same content, use hard links to consolidate duplicate files.
在 3.2 版更改: Added the -i
, -b
and -h
options.
在 3.5 版更改: Added the -j
, -r
, and -qq
options. -q
option was changed to a multilevel value. -b
will always produce a byte-code file ending in .pyc
, never .pyo
.
在 3.7 版更改: Added the --invalidation-mode
option.
在 3.9 版更改: Added the -s
, -p
, -e
and --hardlink-dupes
options. Raised the default recursion limit from 10 to sys.getrecursionlimit()
. Added the possibility to specify the -o
option multiple times.
There is no command-line option to control the optimization level used by the compile()
function, because the Python interpreter itself already provides the option: python -O -m compileall.
Similarly, the compile()
function respects the sys.pycache_prefix
setting. The generated bytecode cache will only be useful if compile()
is run with the same sys.pycache_prefix
(if any) that will be used at runtime.
Public functions
compileall.compile_dir
(dir, maxlevels=sys.getrecursionlimit(), ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=- 1, workers=1, invalidation_mode=None, **, stripdir=None, prependdir=None, limit_sl_dest=None, hardlink_dupes=False*)
Recursively descend the directory tree named by dir, compiling all .py
files along the way. Return a true value if all the files compiled successfully, and a false value otherwise.
The maxlevels parameter is used to limit the depth of the recursion; it defaults to sys.getrecursionlimit()
.
If ddir is given, it is prepended to the path to each file being compiled for use in compilation time tracebacks, and is also compiled in to the byte-code file, where it will be used in tracebacks and other messages in cases where the source file does not exist at the time the byte-code file is executed.
If force is true, modules are re-compiled even if the timestamps are up to date.
If rx is given, its search
method is called on the complete path to each file considered for compilation, and if it returns a true value, the file is skipped. This can be used to exclude files matching a regular expression, given as a re.Pattern object.
If quiet is False
or 0
(the default), the filenames and other information are printed to standard out. Set to 1
, only errors are printed. Set to 2
, all output is suppressed.
If legacy is true, byte-code files are written to their legacy locations and names, which may overwrite byte-code files created by another version of Python. The default is to write files to their PEP 3147 locations and names, which allows byte-code files from multiple versions of Python to coexist.
optimize specifies the optimization level for the compiler. It is passed to the built-in compile()
function. Accepts also a sequence of optimization levels which lead to multiple compilations of one .py
file in one call.
The argument workers specifies how many workers are used to compile files in parallel. The default is to not use multiple workers. If the platform can’t use multiple workers and workers argument is given, then sequential compilation will be used as a fallback. If workers is 0, the number of cores in the system is used. If workers is lower than 0
, a ValueError
will be raised.
invalidation_mode should be a member of the py_compile.PycInvalidationMode
enum and controls how the generated pycs are invalidated at runtime.
The stripdir, prependdir and limit_sl_dest arguments correspond to the -s
, -p
and -e
options described above. They may be specified as str
, bytes
or os.PathLike
.
If hardlink_dupes is true and two .pyc
files with different optimization level have the same content, use hard links to consolidate duplicate files.
在 3.2 版更改: Added the legacy and optimize parameter.
在 3.5 版更改: Added the workers parameter.
在 3.5 版更改: quiet parameter was changed to a multilevel value.
在 3.5 版更改: The legacy parameter only writes out .pyc
files, not .pyo
files no matter what the value of optimize is.
在 3.6 版更改: 接受一个 path-like object。
在 3.7 版更改: The invalidation_mode parameter was added.
在 3.7.2 版更改: The invalidation_mode parameter’s default value is updated to None.
在 3.8 版更改: Setting workers to 0 now chooses the optimal number of cores.
在 3.9 版更改: Added stripdir, prependdir, limit_sl_dest and hardlink_dupes arguments. Default value of maxlevels was changed from 10
to sys.getrecursionlimit()
compileall.compile_file
(fullname, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=- 1, invalidation_mode=None, **, stripdir=None, prependdir=None, limit_sl_dest=None, hardlink_dupes=False*)
Compile the file with path fullname. Return a true value if the file compiled successfully, and a false value otherwise.
If ddir is given, it is prepended to the path to the file being compiled for use in compilation time tracebacks, and is also compiled in to the byte-code file, where it will be used in tracebacks and other messages in cases where the source file does not exist at the time the byte-code file is executed.
If rx is given, its search
method is passed the full path name to the file being compiled, and if it returns a true value, the file is not compiled and True
is returned. This can be used to exclude files matching a regular expression, given as a re.Pattern object.
If quiet is False
or 0
(the default), the filenames and other information are printed to standard out. Set to 1
, only errors are printed. Set to 2
, all output is suppressed.
If legacy is true, byte-code files are written to their legacy locations and names, which may overwrite byte-code files created by another version of Python. The default is to write files to their PEP 3147 locations and names, which allows byte-code files from multiple versions of Python to coexist.
optimize specifies the optimization level for the compiler. It is passed to the built-in compile()
function. Accepts also a sequence of optimization levels which lead to multiple compilations of one .py
file in one call.
invalidation_mode should be a member of the py_compile.PycInvalidationMode
enum and controls how the generated pycs are invalidated at runtime.
The stripdir, prependdir and limit_sl_dest arguments correspond to the -s
, -p
and -e
options described above. They may be specified as str
, bytes
or os.PathLike
.
If hardlink_dupes is true and two .pyc
files with different optimization level have the same content, use hard links to consolidate duplicate files.
3.2 新版功能.
在 3.5 版更改: quiet parameter was changed to a multilevel value.
在 3.5 版更改: The legacy parameter only writes out .pyc
files, not .pyo
files no matter what the value of optimize is.
在 3.7 版更改: The invalidation_mode parameter was added.
在 3.7.2 版更改: The invalidation_mode parameter’s default value is updated to None.
在 3.9 版更改: Added stripdir, prependdir, limit_sl_dest and hardlink_dupes arguments.
compileall.compile_path
(skip_curdir=True, maxlevels=0, force=False, quiet=0, legacy=False, optimize=- 1, invalidation_mode=None)
Byte-compile all the .py
files found along sys.path
. Return a true value if all the files compiled successfully, and a false value otherwise.
If skip_curdir is true (the default), the current directory is not included in the search. All other parameters are passed to the compile_dir()
function. Note that unlike the other compile functions, maxlevels
defaults to 0
.
在 3.2 版更改: Added the legacy and optimize parameter.
在 3.5 版更改: quiet parameter was changed to a multilevel value.
在 3.5 版更改: The legacy parameter only writes out .pyc
files, not .pyo
files no matter what the value of optimize is.
在 3.7 版更改: The invalidation_mode parameter was added.
在 3.7.2 版更改: The invalidation_mode parameter’s default value is updated to None.
To force a recompile of all the .py
files in the Lib/
subdirectory and all its subdirectories:
import compileall
compileall.compile_dir('Lib/', force=True)
# Perform same compilation, excluding files in .svn directories.
import re
compileall.compile_dir('Lib/', rx=re.compile(r'[/\\][.]svn'), force=True)
# pathlib.Path objects can also be used.
import pathlib
compileall.compile_dir(pathlib.Path('Lib/'), force=True)
dis
—- Python 字节码反汇编器
Source code: Lib/dis.py
pickletools
—- pickle 开发者工具集
源代码: Lib/pickletools.py
此模块包含与 pickle
模块内部细节有关的多个常量,一些关于具体实现的详细注释,以及一些能够分析封存数据的有用函数。 此模块的内容对需要操作 pickle
的 Python 核心开发者来说很有用处;pickle
的一般用户则可能会感觉 pickletools
模块与他们无关。
命令行语法
3.2 新版功能.
当从命令行发起调用时,python -m pickletools
将对一个或更多 pickle 文件的内容进行拆解。 请注意如果你查看 pickle 中保存的 Python 对象而非 pickle 格式的细节,你可能需要改用 -m pickle
。 但是,当你想检查的 pickle 文件来自某个不受信任的源时,-m pickletools
是更安全的选择,因为它不会执行 pickle 字节码。
例如,对于一个封存在文件 x.pickle
中的元组 (1, 2)
:
$ python -m pickle x.pickle
(1, 2)
$ python -m pickletools x.pickle
0: \x80 PROTO 3
2: K BININT1 1
4: K BININT1 2
6: \x86 TUPLE2
7: q BINPUT 0
9: . STOP
highest protocol among opcodes = 2
命令行选项
-a``,` `--annotate
使用简短的操作码描述来标注每一行。
-o``,` `--output``=<file>
输出应当写入到的文件名称。
-l``,` `--indentlevel``=<num>
一个新的 MARK 层级所需缩进的空格数。
-m``,` `--memo
当反汇编多个对象时,保留各个反汇编的备忘记录。
-p``,` `--preamble``=<preamble>
当指定一个以上的 pickle 文件时,在每次反汇编之前打印给定的前言。
编程接口
pickletools.dis
(pickle, out=None, memo=None, indentlevel=4, annotate=0)
将 pickle 的符号化反汇编数据输出到文件类对象 out*,默认为 sys.stdout
。 *pickle 可以是一个字符串或一个文件类对象。 memo 可以是一个将被用作 pickle 的备忘记录的 Python 字典;它可被用来对由同一封存器创建的多个封存对象执行反汇编。 由 MARK
操作码指明的每个连续级别将会缩进 indentlevel 个空格。 如果为 annotate 指定了一个非零值,则输出中的每个操作码将以一个简短描述来标注。 annotate 的值会被用作标注所应开始的列的提示。
3.2 新版功能: annotate 参数。
pickletools.genops
(pickle)
提供包含 pickle 中所有操作码的 iterator,返回一个 (opcode, arg, pos)
三元组的序列。 opcode 是 OpcodeInfo
类的一个实例;arg 是 Python 对象形式的 opcode 参数的已解码值;pos 是 opcode 所在的位置。 pickle 可以是一个字符串或一个文件类对象。
pickletools.optimize
(picklestring)
在消除未使用的 PUT
操作码之后返回一个新的等效 pickle 字符串。 优化后的 pickle 将更为简短,耗费更为的传输时间,要求更少的存储空间并能更高效地解封。
Windows系统相关模块
本章节叙述的模块只在 Windows 平台上可用。
msilib
— Read and write Microsoft Installer filesmsvcrt
— 来自 MS VC++ 运行时的有用例程winreg
— 访问 Windows 注册表winsound
—— Windows 系统的音频播放接口
Unix 专有服务
本章描述的模块提供了 Unix 操作系统独有特性的接口,在某些情况下也适用于它的某些或许多衍生版。 以下为模块概览:
posix
— 最常见的 POSIX 系统调用pwd
— 用户密码数据库spwd
—— shadow 密码库grp
— 组数据库crypt
—— 验证 Unix 口令的函数termios
— POSIX 风格的 tty 控制tty
— 终端控制功能pty
— 伪终端工具fcntl
—— 系统调用fcntl
和ioctl
pipes
— 终端管道接口resource
— 资源使用信息nis
— Sun 的 NIS (黄页) 接口- Unix syslog 库例程
- 例子
被取代的模块
本章中描述的模块均已弃用,仅保留用于向后兼容。 它们已经被其他模块所取代。
optparse
— 解析器的命令行选项- 背景
- 教程
- 参考指南
- Option Callbacks
- Defining a callback option
- How callbacks are called
- Raising errors in a callback
- Callback example 1: trivial callback
- Callback example 2: check option order
- Callback example 3: check option order (generalized)
- Callback example 4: check arbitrary condition
- Callback example 5: fixed arguments
- Callback example 6: variable arguments
- Extending
optparse
imp
—— 由代码内部访问 import 。
未创建文档的模块
以下是应当记入文档但是目前尚无文档的模块速览列表。
本章的想法和原内容取自 Fredrik Lundh 的帖子;本章的具体内容已经大幅修改。
平台特定模块
这些模块用于实现 os.path
模块,除此之外没有文档。几乎没有必要创建这些文档。
ntpath
— 在 Win32 和 Win64 平台上实现 os.path
。
posixpath
— 在 POSIX 上实现 os.path
。
Security Considerations
The following modules have specific security considerations:
base64
: base64 security considerations in RFC 4648cgi
: CGI security considerationshashlib
: all constructors take a “usedforsecurity” keyword-only argument disabling known insecure and blocked algorithmshttp.server
is not suitable for production use, only implementing basic security checkslogging
: Logging configuration uses eval()multiprocessing
: Connection.recv() uses picklepickle
: Restricting globals in picklerandom
shouldn’t be used for security purposes, usesecrets
insteadshelve
: shelve is based on pickle and thus unsuitable for dealing with untrusted sourcesssl
: SSL/TLS security considerationssubprocess
: Subprocess security considerationstempfile
: mktemp is deprecated due to vulnerability to race conditionsxml
: XML vulnerabilitieszipfile
: maliciously prepared .zip files can cause disk volume exhaustion