Python-Standard Library


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 suite
    • test.support.socket_helper —- Utilities for socket tests
    • test.support.script_helper —- Utilities for the Python execution tests
    • test.support.bytecode_helper —- Support tools for testing correct bytecode generation
    • test.support.threading_helper —- Utilities for threading tests
    • test.support.os_helper —- Utilities for os tests
    • test.support.import_helper —- Utilities for import tests
    • test.support.warnings_helper —- Utilities for warnings tests
  • 调试和分析
    • 审计事件表
    • bdb —- Debugger framework
    • faulthandler —- Dump the Python traceback
    • pdb —- Python 的调试器
    • Python Profilers 分析器
    • timeit —- 测量小代码片段的执行时间
    • trace —- 跟踪Python语句的执行
    • tracemalloc —- 跟踪内存分配
  • 软件打包和分发
    • distutils —- 构建和安装 Python 模块
    • ensurepip —- Bootstrapping the pip installer
    • venv —- 创建虚拟环境
    • zipapp —- Manage executable Python zip archives
  • Python运行时服务
    • sys —- 系统相关的参数和函数
    • sysconfig —- Provide access to Python’s configuration information
    • builtins —- 内建对象
    • __main__ —- Top-level code environment
    • warnings —— 警告信息的控制
    • 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 tables
    • token —- 与Python解析树一起使用的常量
    • keyword —- 检验Python关键字
    • tokenize —- 对 Python 代码使用的标记解析器
    • tabnanny —- 模糊缩进检测
    • pyclbr —- Python 模块浏览器支持
    • py_compile —- 编译 Python 源文件
    • compileall —- Byte-compile Python libraries
    • dis —- Python 字节码反汇编器
    • pickletools —- pickle 开发者工具集
  • Windows系统相关模块
    • msilib —- Read and write Microsoft Installer files
    • msvcrt —- 来自 MS VC++ 运行时的有用例程
    • winreg —- 访问 Windows 注册表
    • winsound —— Windows 系统的音频播放接口
  • Unix 专有服务
    • posix —- 最常见的 POSIX 系统调用
    • pwd —- 用户密码数据库
    • spwd —- The shadow password database
    • grp —- 组数据库
    • crypt —— 验证 Unix 口令的函数
    • termios —- POSIX 风格的 tty 控制
    • tty —- 终端控制功能
    • pty —- 伪终端工具
    • fcntl —— 系统调用 fcntlioctl
    • pipes —- 终端管道接口
    • resource —- Resource usage information
    • nis —- 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, 34。两个片段的长度应相同。如果发生溢出,较长的采样将被截断。

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。

参数 weightAweightB 是简单数字滤波器的参数,默认分别为 10

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 声音格式的便利接口。请注意此模块与 aifcwave 是兼容接口的。

音频文件由标头和数据组成。标头的字段为:

目录
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.htmlhttps://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 新版功能: exrwebp 格式被添加。

你可以扩展此 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 也会返回实际值或者在无法推测或者难以解码时返回 0frames 则是实际值或 -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:

  1. setfmt() to set the output format
  2. channels() to set the number of channels
  3. speed() 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_MESSAGESLANG` 中。

如果遗漏了 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)

修改或查询当前的全局域。如果 domainNone,则返回当前的全局域,不为 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() 接受的域相同。可选参数 *localedirbindtextdomain() 中的相同。可选参数 languages 是多条字符串的列表,其中每条字符串都是一种语言代码。

如果没有传入 localedir,则使用默认的系统语言环境目录。如果没有传入 *languages,则搜索以下环境变量:LANGUAGELC_ALLLC_MESSAGESLANG。从这些变量返回的第一个非空值将用作 *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)

根据 domainlocaledirlanguages,返回 *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() 函数的 domainlocaledircodeset,在 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)

    在编目中查找 contextmessage 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 程序提供不同语言的消息,需要执行以下步骤:

  1. 准备程序或模块,将可翻译的字符串特别标记起来
  2. 在已标记的文件上运行一套工具,用来生成原始消息编目
  3. 创建消息编目的不同语言的翻译
  4. 使用 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.pymsgfmt.py,某些 Python 发行版已经安装了它们。pygettext.py 类似于 xgettext,但只能理解 Python 源代码,无法处理诸如 C 或 C++ 的其他编程语言。pygettext.py 支持的命令行界面类似于 xgettext,查看其详细用法请运行 pygettext.py --helpmsgfmt.py 与 GNU msgfmt 是二进制兼容的。有了这两个程序,可以不需要 GNU gettext 包来国际化 Python 应用程序。)

xgettextpygettext 或类似工具生成的 .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 extractxpot 都支持此功能,使用 -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 in re.

  • 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 the time.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”个类:

  1. TurtleScreen 类定义图形窗口作为绘图海龟的运动场。它的构造器需要一个 tkinter.CanvasScrolledCanvas 作为参数。应在 turtle 作为某个程序的一部分的时候使用。

    Screen() 函数返回一个 TurtleScreen 子类的单例对象。此函数应在 turtle 作为独立绘图工具时使用。作为一个单例对象,其所属的类是不可被继承的。

    TurtleScreen/Screen 的所有方法还存在对应的函数,即作为面向过程的接口组成部分。

  2. RawTurtle (别名: RawPen) 类定义海龟对象在 TurtleScreen 上绘图。它的构造器需要一个 Canvas, ScrolledCanvas 或 TurtleScreen 作为参数,以指定 RawTurtle 对象在哪里绘图。

    从 RawTurtle 派生出子类 Turtle (别名: Pen),该类对象在 Screen 实例上绘图,如果实例不存在则会自动创建。

    RawTurtle/Turtle 的所有方法也存在对应的函数,即作为面向过程的接口组成部分。

过程式接口提供与 ScreenTurtle 类的方法相对应的函数。函数名与对应的方法名相同。当 Screen 类的方法对应函数被调用时会自动创建一个 Screen 对象。当 Turtle 类的方法对应函数被调用时会自动创建一个 (匿名的) Turtle 对象。

如果屏幕上需要有多个海龟,就必须使用面向对象的接口。

turtle简易教程

shlex —— 简单的词法分析

源代码: Lib/shlex.py


shlex 类可用于编写类似 Unix shell 的简单词法分析程序。通常可用于编写“迷你语言”(如 Python 应用程序的运行控制文件)或解析带引号的字符串。

shlex 模块中定义了以下函数:

shlex.split(s, comments=False, posix=True)

用类似 shell 的语法拆分字符串 s。如果 commentsFalse (默认值),则不会解析给定字符串中的注释 (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_splitFalse,则未声明为单词字符、空白或引号的字符将作为单字符的词法单元返回。若为 True, 则 shlex 只根据空白符拆分单词。
  • EOF 用空字符串('')表示;
  • 空字符串无法解析,即便是加了引号。

在 POSIX 模式时,shlex 将尝试遵守以下解析规则:

  • 引号会被剔除,且不会拆分单词( "Do"Not"Separate" 将解析为单个单词 DoNotSeparate);
  • 未加引号包裹的转义字符(如 '\' )保留后一个字符的字面意思;
  • 引号中的字符不属于 escapedquotes (例如,"'"),则保留引号中所有字符的字面值;
  • 若引号包裹的字符属于 escapedquotes (例如 '"'),则保留引号中所有字符的字面意思,属于 escape 中的字符除外。仅当后跟后半个引号或转义字符本身时,转义字符才保留其特殊含义。否则,转义字符将视作普通字符;
  • EOF 用 None 表示;
  • 允许出现引号包裹的空字符串('')。

改进的 shell 兼容性

3.6 新版功能.

shlex 类提供了与常见 Unix shell(如 bashdashsh)的解析兼容性。为了充分利用这种兼容性,请在构造函数中设定 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 时始终使用 posixwhitespace_split ,这将完全否定 wordchars

为了达到最佳效果,punctuation_chars 应与 posix=True 一起设置。(注意 posix=Falseshlex 的默认设置)。

cmd —- 支持面向行的命令解释器

源代码: Lib/cmd.py


Cmd 类提供简单框架用于编写面向行的命令解释器。 这些通常对测试工具,管理工具和原型有用,这些工具随后将被包含在更复杂的接口中。

class cmd.Cmd(completekey=’tab’, stdin=None, stdout=None)

一个 Cmd 实例或子类实例是面向行的解释器框架结构。 实例化 Cmd 本身是没有充分理由的, 它作为自定义解释器类的超类是非常有用的为了继承 Cmd 的方法并且封装动作方法。

可选参数 completekey 是完成键的 readline 名称;默认是 Tab 。如果 completekey 不是 None 并且 readline 是可用的, 命令完成会自动完成。

可选参数 stdinstdout 指定了Cmd实例或子类实例将用于输入和输出的输入和输出文件对象。如果没有指定,他们将默认为 sys.stdinsys.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() 方法返回一个真值 。参数 stoppostcmd() 是命令对应的返回值 do_*() 的方法。

如果激活了完成,全部命令将会自动完成,并且通过调用 complete_foo() 参数 text , line, begidx ,和 endidx 完成全部命令参数。 text 是我们试图匹配的字符串前缀,所有返回的匹配项必须以它为开头。 line 是删除了前导空格的当前的输入行, begidxendidx 是前缀文本的开始和结束索引。,可以用于根据参数位置提供不同的完成。

所有 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 框架和工具

开发工具

本章中描述的各模块可帮你编写 Python 程序。例如,pydoc 模块接受一个模块并根据该模块的内容来生成文档。doctestunittest 这两个模块包含了用于编写单元测试的框架,并可用于自动测试所编写的代码,验证预期的输出是否产生。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
  • 2to3 - 自动将 Python 2 代码转为 Python 3 代码
    • 使用 2to3
    • 修复器
    • lib2to3 —— 2to3 支持库
  • test —- Python回归测试包
    • Writing Unit Tests for the test package
    • Running tests using the command-line interface
  • test.support —- Utilities for the Python test suite
  • test.support.socket_helper —- Utilities for socket tests
  • test.support.script_helper —- Utilities for the Python execution tests
  • test.support.bytecode_helper —- Support tools for testing correct bytecode generation
  • test.support.threading_helper —- Utilities for threading tests
  • test.support.os_helper —- Utilities for os tests
  • test.support.import_helper —- Utilities for import tests
  • test.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。子类型也可以当作参数。

类型别名

把类型赋给别名,就可以定义类型别名。本例中,Vectorlist[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 时,静态类型检查器认为 AliasOriginal 完全等价。 这种方式适用于简化复杂类型签名。

反之,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 当作 应急出口

Anyobject 的区别。与 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 静态类型系统定义为应用 名义子类型。即,当且仅当 AB 的子类时,才能在预期 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, ...]TupleTuple[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 and Concatenate).
  • ParamSpec and Callable.

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=Trueget_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:

  1. The return value is a boolean.

  2. If the return value is True, the type of its argument is the type inside TypeGuard.

    例如:

    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=Truecontravariant=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:

  1. The type checker can’t type check the inner function because *args and **kwargs have to be typed Any.
  2. cast() may be required in the body of the add_logging decorator when returning the inner function, or the static type checker must be told to ignore the return inner.
  • args

  • kwargs

    Since ParamSpec captures both positional and keyword parameters, P.args and P.kwargs can be used to split a ParamSpec 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 and P.kwargs are instances respectively of ParamSpecArgs and ParamSpecKwargs.

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 and Concatenate).
  • Callable and Concatenate.
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.abcIterable 非常类似,只擅长做一件事。 例如:

@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 的泛型版本。适用于注解返回类型。注解参数时,最好使用 SequenceIterable 等抽象容器类型。

该类型用法如下:

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 模块中的 PatternMatch 类现已支持 []。详见 PEP 585 与 Generic Alias Type。

class typing.Text

Textstr 的别名。提供了对 Python 2 代码的向下兼容:Python 2 中,Textunicode 的别名。

使用 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 的泛型版本。

该类型代表了 bytesbytearraymemoryview 等字节序列类型。

作为该类型的简称,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 模块里的其他泛型不同, GeneratorSendType 属于逆变行为,不是协变行为,也是不变行为。

如果生成器只产生值,可将 SendTypeReturnType 设为 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__ 相同。此外,可通过在 globalslocals 命名空间里进行评估,以此来处理编码为字符串字面量的前向引用。如有需要,在默认值设置为 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 将启动在给定主机名上执行监听的服务。 默认主机名为 ‘localhost’ 但如果你希望能从其他机器搜索该服务器,你可能会想要改变服务器所响应的主机名。 在开发阶段此特性会特别有用,因为这样你将能在一个容器中运行 pydoc。

pydoc -b 将启动服务并额外打开一个 Web 浏览器访问模块索引页。 所发布的每个页面顶端都带有导航栏,你可以点击 Get 获取特定条目的帮助,点击 Search 在所有模块的提要行中搜索特定关键词,或是点击 Module index, TopicsKeywords 前往相应的页面。

pydoc 生成文档内容时,它会使用当前环境和路径来定位模块。 因此,发起调用 pydoc spam 得到的文档版本会与你启动 Python 解释器并输入 import spam 时得到的模块版本完全相同。

核心模块的模块文档位置对应于 https://docs.python.org/X.Y/library/ 其中 XY 是 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”.

doctest

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 参数则可以明确指定不使用的修复器。下面的例子会只使用 importshas_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 语句的代码运行修复器。 也可以使用 -eexec() 解读为函数。

-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 SomeClasstype(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_valuesys.exc_typesys.exc_traceback 替换为 sys.exc_info() 的用法。

throw

修复生成器的 throw() 方法的 API 变更。

tuple_params

移除隐式的元组参数解包。这个修复器会插入临时变量。

types

修复 type 模块中一些成员的移除引起的代码问题。

unicode

unicode 重命名为 str

urllib

urlliburllib2 重命名为 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回归测试包

调试和分析

这些库可以帮助你进行 Python 开发:调试器使你能够逐步执行代码,分析堆栈帧并设置中断点等等,性能分析器可以运行代码并为你提供执行时间的详细数据,使你能够找出你的程序中的瓶颈。 审计事件提供运行时行为的可见性,如果没有此工具则需要进行侵入式调试或修补。

审计事件表

下表包含了在整个 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 the pip 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>: Installs pip 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: Installs pip 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, the pipX script will not be installed.
  • --default-pip: if a “default pip” installation is requested, the pip 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

参见

Python 打包用户指南:创建和使用虚拟环境

创建虚拟环境

通过执行 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 安装 配置好 PATHPATHEXT 变量:

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 选项,否则将会调用 ensurepippip 引导到虚拟环境中。

可以向 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 新版功能: fishcsh 激活脚本。

3.8 新版功能: 在 POSIX 上安装 PowerShell 激活脚本,以支持 PowerShell Core。

注解

虚拟环境是一个 Python 环境,安装到其中的 Python 解释器、库和脚本与其他虚拟环境中的内容是隔离的,且(默认)与“系统级” Python(操作系统的一部分)中安装的库是隔离的。

虚拟环境是一个目录树,其中包含 Python 可执行文件和其他文件,其他文件指示了这是一个是虚拟环境。

常用安装工具如 setuptools 和 pip 可以在虚拟环境中按预期工作。换句话说,当虚拟环境被激活,它们就会将 Python 软件包安装到虚拟环境中,无需明确指示。

当虚拟环境被激活(即虚拟环境的 Python 解释器正在运行),属性 sys.prefixsys.exec_prefix 指向的是虚拟环境的基础目录,而 sys.base_prefixsys.base_exec_prefix 指向非虚拟环境的 Python 安装,即曾用于创建虚拟环境的那个 Python 安装。如果虚拟环境没有被激活,则 sys.prefixsys.base_prefix 相同,且 sys.exec_prefixsys.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)

    创建环境目录和所有必需的目录,并返回一个上下文对象。该对象只是一个容器,保存属性(如路径),供其他方法使用。允许目录已经存在,如果指定了 clearupgrade 就允许在现有环境目录上进行操作。

  • create_configuration(context)

    在环境中创建 pyvenv.cfg 配置文件。

  • setup_python(context)

    在环境中创建 Python 可执行文件的拷贝或符号链接。在 POSIX 系统上,如果给定了可执行文件 python3.x,将创建指向该可执行文件的 pythonpython3 符号链接,除非相同名称的文件已经存在。

  • setup_scripts(context)

    将适用于平台的激活脚本安装到虚拟环境中。

  • upgrade_dependencies(context)

    升级环境中 venv 依赖的核心软件包(当前为 pipsetuptools)。通过在环境中使用 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 目录的名称( binScripts )。
    • __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:

  1. Create your application in a directory as normal, so you have a myapp directory containing a __main__.py file, and any supporting application code.

  2. 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).

  3. Optionally, delete the .dist-info directories created by pip in the myapp 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.

  4. 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.

  1. 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 in sys.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 to sys.path at runtime, based on the user’s machine).
  2. 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.
  3. 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 the multiprocessing module, it will need to call multiprocessing.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:

  1. 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 in sys.getfilesystemencoding() on POSIX.
  2. 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 Objects
    • StackSummary Objects
    • FrameSummary 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 发现处于一个虚拟环境中, prefixexec_prefix 将会指向虚拟环境。然而 base_prefixbase_exec_prefix 将仍然会指向基础的 Python 环境(用来创建虚拟环境的 Python 环境)

3.3 新版功能.

sys.base_prefix

site.py 运行之前, Python 启动的时候被设置为跟 prefix 同样的值。如果不是运行在 虚拟环境 中, 两个值会保持相同;如果 site.py 发现处于一个虚拟环境中, prefixexec_prefix 将会指向虚拟环境。然而 base_prefixbase_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 文件。该值会被初始化为 TrueFalse,依据是 -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__

程序开始时,这些对象存有 breakpointhookdisplayhookexcepthookunraisablehook 的初始值。保存它们是为了可以在 breakpointhookdisplayhookexcepthookunraisablehook 被破坏或被替换时恢复它们。

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',那么对于(非无穷的)浮点数 xrepr(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,则返回从栈顶往下相应调用层数的帧对象。如果该数比调用栈更深,则抛出 ValueErrordepth 的默认值是 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_typeplatform_versionservice_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_maskproduct_type

在 3.6 版更改: 添加了 platform_version

sys.get_asyncgen_hooks()

返回一个 asyncgen_hooks 对象,该对象类似于 namedtuple,形式为 (firstiter, finalizer),其中 firstiterfinalizerNone 或函数,函数以 异步生成器迭代器 作为参数,并用于在事件循环中干预异步生成器的终结。

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_bitsseed_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 曾是 0xFFFF0x10FFFF,具体取决于配置选项,该选项指定将 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。性能分析函数中的错误将导致其自身被解除设置。

性能分析函数应接收三个参数:frameeventargframe 是当前的堆栈帧。event 是一个字符串:'call''return''c_call''c_return''c_exception'arg 取决于事件类型。

引发一个 审计事件 sys.setprofile,不附带任何参数。

这些事件具有以下含义:

  • 'call'

    表示调用了某个函数(或进入了其他的代码块)。性能分析函数将被调用,argNone

    'return'

    表示某个函数(或别的代码块)即将返回。性能分析函数将被调用,arg 是即将返回的值,如果此次返回事件是由于抛出异常,argNone

    '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()

跟踪函数应接收三个参数:frameeventargframe 是当前的堆栈帧。event 是一个字符串:'call''line''return''exception''opcode'arg 取决于事件类型。

每次进入 trace 函数的新的局部作用范围,都会调用 trace 函数( event 会被设置为 'call' ),它应该返回一个引用,指向即将用在新作用范围上的局部跟踪函数;如果不需要跟踪当前的作用范围,则返回 None

局部跟踪函数应返回对自身的引用(或对另一个函数的引用,用来在其作用范围内进行进一步的跟踪),或者返回 None 来停止跟踪其作用范围。

如果跟踪函数出错,则该跟踪函数将被取消设置,类似于调用 settrace(None)

这些事件具有以下含义:

  • 'call'

    表示调用了某个函数(或进入了其他的代码块)。全局跟踪函数将被调用,argNone。返回值将指定局部跟踪函数。

    'line'

    表示解释器即将执行新一行代码或重新执行循环条件。局部跟踪函数将被调用,argNone,其返回值将指定新的局部跟踪函数。关于其工作原理的详细说明,请参见 Objects/lnotab_notes.txt。要在该堆栈帧禁用每行触发事件,可以在堆栈帧上将 f_trace_lines 设置为 False

    'return'

    表示某个函数(或别的代码块)即将返回。局部跟踪函数将被调用,arg 是即将返回的值,如果此次返回事件是由于抛出异常,argNone。跟踪函数的返回值将被忽略。

    'exception'

    表示发生了某个异常。局部跟踪函数将被调用,arg 是一个 (exception, value, traceback) 元组,返回值将指定新的局部跟踪函数。

    'opcode'

    表示解释器即将执行一个新的操作码。局部跟踪函数将被调用,argNone,其返回值将指定新的局部跟踪函数。每操作码触发事件默认情况下都不发出:必须在堆栈帧上将 f_trace_opcodes 显式地设置为 True 来请求这些事件。

注意,由于异常是在链式调用中传播的,所以每一级都会产生一个 'exception' 事件。

更细微的用法是,可以显式地通过赋值 frame.f_trace = tracefunc 来设置跟踪函数,而不是用现有跟踪函数的返回值去间接设置它。当前帧上的跟踪函数必须激活,而 settrace() 还没有做这件事。注意,为了使上述设置起效,必须使用 settrace() 来安装全局跟踪函数才能启用运行时跟踪机制,但是它不必与上述是同一个跟踪函数(它可以是一个开销很低的跟踪函数,只返回 None,即在各个帧上立即将其自身禁用)。

引发一个 审计事件 sys.settrace,不附带任何参数。

CPython implementation detail: settrace() 函数仅用于实现调试器,性能分析器,打包工具等。它的行为是实现平台的一部分,而不是语言定义的一部分,因此并非在所有 Python 实现中都可用。

在 3.7 版更改: 添加了 'opcode' 事件类型;为帧对象添加了 f_trace_linesf_trace_opcodes 属性

sys.set_asyncgen_hooks(firstiter, finalizer)

接受两个可选的关键字参数,要求它们是可调用对象,且接受一个 异步生成器迭代器 作为参数。firstiter 对象将在异步生成器第一次迭代时调用。finalizer 将在异步生成器即将被销毁时调用。

引发一个 审计事件 sys.set_asyncgen_hooks_firstiter,不附带任何参数。

引发一个 审计事件 sys.set_asyncgen_hooks_finalizer,不附带任何参数。

之所以会引发两个审计事件,是因为底层的 API 由两个调用组成,每个调用都须要引发自己的事件。

3.6 新版功能: 更多详情请参阅 PEP 525finalizer 方法的参考示例可参阅 Lib/asyncio/base_events.pyasyncio.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_encodingPyConfig.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__

程序开始时,这些对象存有 stdinstderrstdout 的初始值。它们在程序结束前都可以使用,且在需要向实际的标准流打印内容时很有用,无论 sys.std* 对象是否已重定向。

如果实际文件已经被覆盖成一个损坏的对象了,那它也可用于将实际文件还原成能正常工作的文件对象。但是,本过程的最佳方法应该是,在原来的流被替换之前就显式地保存它,并使用这一保存的对象来还原。

注解

某些情况下的 stdinstdoutstderr 以及初始值 __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_msgobject 格式化为: f'{err_msg}: {object!r}';如果 err_msgNone 则采用 “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, releaselevelserial*。 除 *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:

  1. the name of the top-level environment of the program, which can be checked using the __name__ == '__main__' expression; and
  2. 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 bytesbytearray 相关警告的基类。
ResourceWarning 资源利用相关警告的基类。

在 3.7 版更改: 以前 DeprecationWarningFutureWarning 是根据某个功能是否完全删除或改变其行为来区分的。现在是根据受众和默认警告过滤器的处理方式来区分的。

警告过滤器

警告过滤器控制着警告是否被忽略、显示或转为错误(触发异常)。

从概念上讲,警告过滤器维护着一个经过排序的过滤器类别列表;任何具体的警告都会依次与列表中的每种过滤器进行匹配,直到找到一个匹配项;过滤器决定了匹配项的处理方式。每个列表项均为 ( 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 必须是个字符串,categoryWarning 的子类;或者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 是要包含在警告信息中的一行源代码;如果未提供 lineshowwarning() 将尝试读取由filenamelineno 指定的行。

warnings.formatwarning(message, category, filename, lineno, line=None)

以标准方式格式化一条警告信息。将返回一个字符串,可能包含内嵌的换行符,并以换行符结束。如果未提供 line*,formatwarning() 将尝试读取由 *filenamelineno 指定的行。

warnings.filterwarnings(action, message=’’, category=Warning, module=’’, lineno=0, append=False)

在 警告过滤器种类 列表中插入一条数据项。默认情况下,该数据项将被插到前面;如果 append 为 True,则会插到后面。这里会检查参数的类型,编译 messagemodule 正则表达式,并将他们作为一个元组插入警告过滤器的列表中。如果两者都与某种警告匹配,那么靠近列表前面的数据项就会覆盖后面的项。省略的参数默认匹配任意值。

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。 如果 recordTrue,则返回一个列表,列表由自定义 showwarning() 函数所用对象逐步填充(该函数还会抑制 sys.stdout 的输出)。 列表中每个对象的属性与 showwarning() 的参数名称相同。

module 参数代表一个模块,当导入 warnings 时,将被用于代替返回的模块,其过滤器将被保护。该参数主要是为了测试 warnings 模块自身。

注解

catch_warnings 管理器的工作方式,是替换并随后恢复模块的 showwarning() 函数和内部的过滤器种类列表。这意味着上下文管理器将会修改全局状态,因此不是线程安全的。

dataclasses —- 数据类

源码: Lib/dataclasses.py


这个模块提供了一个装饰器和一些函数,用于自动添加生成的 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() 装饰器会检查类以查找 fieldfield 被定义为具有 类型标注 的类变量。 除了下面描述的两个例外,在 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 (默认值),则根据 eqfrozen 的设置方式生成 __hash__() 方法。

    __hash__() 由内置的 hash() 使用,当对象被添加到散列集合(如字典和集合)时。有一个 __hash__() 意味着类的实例是不可变的。可变性是一个复杂的属性,取决于程序员的意图, __eq__() 的存在性和行为,以及 dataclass() 装饰器中 eqfrozen 标志的值。

    默认情况下, dataclass() 不会隐式添加 __hash__() 方法,除非这样做是安全的。 它也不会添加或更改现有的明确定义的 __hash__() 方法。 设置类属性 __hash__ = None 对 Python 具有特定含义,如 __hash__() 文档中所述。

    如果 __hash__() 没有显式定义,或者它被设为 None,则 dataclass() 可能 会添加一个隐式 __hash__() 方法。 虽然并不推荐,但你可以用 unsafe_hash=True 来强制 dataclass() 创建一个 __hash__() 方法。 如果你的类在逻辑上不可变但却仍然可被修改那么可能就是这种情况。 这是一个特殊用例并且应当被仔细地考虑。

    以下是隐式创建 __hash__() 方法的规则。请注意,你不能在数据类中都使用显式的 __hash__() 方法并设置 unsafe_hash=True ;这将导致 TypeError

    如果 eqfrozen 都是 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 新版功能.

fields 可以选择使用普通的 Python 语法指定默认值:

@dataclass
class C:
    a: int       # 'a' has no default value
    b: int = 0   # assign a default value for 'b'

在这个例子中, ab 都将包含在添加的 __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 :如果提供,它必须是一个零参数可调用对象,当该字段需要一个默认值时,它将被调用。除了其他目的之外,这可以用于指定具有可变默认值的字段,如下所述。 同时指定 defaultdefault_factory 将产生错误。

  • init :如果为true(默认值),则该字段作为参数包含在生成的 __init__() 方法中。

  • repr :如果为true(默认值),则该字段包含在生成的 __repr__() 方法返回的字符串中。

  • hash :这可以是布尔值或 None 。如果为true,则此字段包含在生成的 __hash__() 方法中。如果为 None (默认值),请使用 compare 的值,这通常是预期的行为。如果字段用于比较,则应在 hash 中考虑该字段。不鼓励将此值设置为 None 以外的任何值。

    设置 hash=Falsecompare=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.xC.y 将不设置。

class dataclasses.Field

Field 对象描述每个定义的字段。这些对象在内部创建,并由 fields() 模块级方法返回(见下文)。用户永远不应该直接实例化 Field 对象。 其有文档的属性是:

  • name :字段的名字。
  • type :字段的类型。
  • default, default_factory, init, repr, hash, compare, metadatakw_only 具有与 field() 函数中对应参数相同的含义和值。

可能存在其他属性,但它们是私有的,不能被审查或依赖。

dataclasses.fields(class_or_instance)

返回 Field 对象的元组,用于定义此数据类的字段。 接受数据类或数据类的实例。如果没有传递一个数据类或实例将引发 TypeError 。 不返回 ClassVarInitVar 的伪字段。

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 会被用作 typeinit, repr, eq, order, unsafe_hash, frozen, match_args, kw_onlyslots 等值与它们在 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__() 形参必须以关键字形式来指定。

在这个例子中,字段 yz 将被标记为仅限关键字字段:

@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() 将返回 ijField 对象,但不包括 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

最后的字段列表依次是 xyzx 的最终类型是 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.xD.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, dictset 的默认形参时将会引发 TypeError。 这是一个部分解决方案,但它确实能防止许多常见错误。

使用默认工厂函数是一种创建可变类型新实例的方法,并将其作为字段的默认值:

@dataclass
class D:
    x: list = field(default_factory=list)
assert D().x is not D().x

contextlib —- 为 with语句上下文提供的工具

源代码 Lib/contextlib.py


此模块为涉及 with 语句的常见任务提供了实用的工具。

工具

提供的函数和类:

class contextlib.AbstractContextManager

一个为实现了 object.__aenter__()object.__aexit__() 的类提供的 abstract base class。 为 object.__aenter__() 提供的一个默认实现是返回 selfobject.__aexit__() 是一个默认返回 None 的抽象方法。

3.6 新版功能.

class contextlib.AbstractAsyncContextManager

一个为实现了 object.__aenter__()object.__aexit__() 的类提供的 abstract base class。 为 object.__aenter__() 提供的一个默认实现是返回 selfobject.__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 时重新被引发。 因此,你可以使用 tryexceptfinally 语句来捕获该异常(如果有的话),或确保进行了一些清理。 如果仅出于记录日志或执行某些操作(而非完全抑制异常)的目的捕获了异常,生成器必须重新引发该异常。 否则生成器的上下文管理器将向 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 with async 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 a with 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。如果返回 Truesubclass 就会被认为是这个抽象基类的子类。如果返回 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, BC, 那么在解释器终止时会依序执行 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)

打印回溯对象 tbfile 的异常信息和整个堆栈回溯。这和 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 by walk_stack() or walk_tb()).

    If limit is supplied, only this many frames are taken from frame_gen. If lookup_lines is False, the returned FrameSummary objects will not have read their lines in yet, making the cost of creating the StackSummary cheaper (which may be valuable if it may not actually get formatted). If capture_locals is True the local variables in each FrameSummary are captured as object representations.

  • classmethod from_list(a_list)

    Construct a StackSummary object from a supplied list of FrameSummary 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

在垃圾回收器开始前和完成后会被调用的一系列回调函数。这些回调函数在被调用时使用两个参数: phaseinfo

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 a TypeError.

  • bind_partial(\args, *kwargs)

    Works the same way as Signature.bind(), but allows the omission of some required arguments (mimics functools.partial() behavior.) Returns BoundArguments, or raises a TypeError 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/or return_annotation to override the corresponding properties of the base signature. To remove return_annotation from the copied Signature, pass in Signature.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 callable obj. Pass follow_wrapped=False to get a signature of obj without unwrapping its __wrapped__ chain. globalns and localns 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 and localns 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, like Parameter.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, pass Parameter.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 in args and kwargs.

    Should be used in conjunction with Signature.parameters for any argument processing purposes.

    注解

    Arguments for which Signature.bind() or Signature.bind_partial() relied on a default value are skipped. However, if needed, use BoundArguments.apply_defaults() to add them.

    在 3.9 版更改: arguments is now of type dict. Formerly, it was of type collections.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 type str will be un-stringized using eval(). 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() and dict.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 type str. (Note that get_annotations doesn’t catch exceptions; if eval() raises an exception, it will unwind the stack past the get_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 to obj.__dict__.
  • If obj is a class, globals defaults to sys.modules[obj.__module__].__dict__ and locals defaults to the obj class namespace.
  • If obj is a callable, globals defaults to obj.__globals__, although if obj is a wrapped function (using functools.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.prefixsys.exec_prefix 已经被设置为 /usr/local。 Python X.Y 的库之后被安装为 /usr/local/lib/python*X.Y*。假设有一个拥有三个孙目录 foo, barspam 的子目录 /usr/local/lib/python*X.Y*/site-packages,并且有两个路径配置文件 foot.pthbar.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.prefixsys.exec_prefix 均为空值,并且路径操作会被跳过;但是仍然会尝试导入 sitecustomizeusercustomize

Readline 配置

在支持 readline 的系统上,这个模块也将导入并配置 rlcompleter 模块,如果 Python 是以 交互模式 启动并且不带 -S 选项的话。 默认的行为是启用 tab 键补全并使用 ~/.python_history 作为历史存档文件。 要禁用它,请删除(或重载)你的 sitecustomizeusercustomize 模块或 PYTHONSTARTUP 文件中的 sys.__interactivehook__ 属性。

在 3.4 版更改: rlcompleter 和 history 会被自动激活。

模块内容

site.PREFIXES

site-packages 目录的前缀列表。

site.ENABLE_USER_SITE

显示用户 site-packages 目录状态的旗标。 True 意味着它被启用并被添加到 sys.pathFalse 意味着它按照用户请求被禁用 (通过 -sPYTHONNOUSERSITE)。 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 文件。 通常被用于 sitecustomizeusercustomize (见下文)。

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.ps1sys.ps2 作为输入提示符,并有输入缓冲。

code.interact(banner=None, readfunc=None, local=None, exitmsg=None)

运行一个 read-eval-print 循环的便捷函数。这会创建一个新的 InteractiveConsole 实例。如果提供了 readfunc ,会设置为 InteractiveConsole.raw_input() 方法。如果提供了 local ,则将其传递给 InteractiveConsole 的构造函数,以用作解释器循环的默认命名空间。然后,如果提供了 bannerexitmsg ,实例的 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;如果命令完整但包含语法错误则会引发 SyntaxErrorOverflowError 而如果命令包含无效字面值则将引发 ValueError

交互解释器对象

InteractiveInterpreter.runsource(source, filename=’<input>’, symbol=’single’)

在解释器中编译并运行一段源码。 所用参数与 compile_command() 一样;filename 的默认值为 '<input>'symbol 则为 'single'。 可能发生以下情况之一:

  • 输入不正确;compile_command() 引发了一个异常 (SyntaxErrorOverflowError)。 将通过调用 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 模块。

这个任务有两个部分:

  1. 能够判断一行输入是否完成了一个Python语句:简而言之,告诉我们是否要打印 ‘>>>‘ 或 ‘...‘。
  2. 记住用户已输入了哪些 future 语句,这样后续的输入可以在这些语句被启用的状态下被编译。

codeop 模块提供了分别以及同时执行这两个部分的方式。

只执行前一部分:

codeop.compile_command(source, filename=’, symbol=’single’)

尝试编译 source*,这应当是一个 Python 代码字符串,并且在 *source 是有效的 Python 代码时返回一个代码对象。 在此情况下,代码对象的 filename 属性将为 filename*,其默认值为 '<input>'。 如果 *source 不是 有效的 Python 代码而是有效的 Python 代码的一个前缀时将返回 None

如果 source 存在问题,将引发异常。 如果存在无效的 Python 语法将引发 SyntaxError,而如果存在无效的字面值则将引发 OverflowErrorValueError

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 hooks
    • importlib.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 档案。

参见

PKZIP Application Note

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/libarchivepath 将在 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 对象的空字符串。

当与斜杠结合使用时, archiveprefix 属性等价于赋予 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, ImportErrors 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 —- 查找脚本使用的模块

源码: Lib/modulefinder.py


该模块提供了一个 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.pathdebug 设置调试级别;更高的值使类打印调试消息,关于它正在做什么。 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_namemod_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 新版功能.

源代码 Lib/importlib/init.py


概述

importlib 包的目的有两个。 第一个目的是在 Python 源代码中提供 import 语句的实现(并且因此而扩展 __import__() 函数)。 这提供了一个可移植到任何 Python 解释器的 import 实现。 相比使用 Python 以外的编程语言实现方式,这一实现更加易于理解。

第二个目的是实现 import 的部分被公开在这个包中,使得用户更容易创建他们自己的自定义对象 (通常被称为 importer) 来参与到导入过程中。

参见

import 语句

import 语句的语言参考

包规格说明

包的初始规范。自从编写这个文档开始,一些语义已经发生改变了(比如基于 sys.modulesNone 的重定向)。

__import__() 函数

import 语句是这个函数的语法糖。

PEP 235

在忽略大小写的平台上进行导入

PEP 263

定义 Python 源代码编码

PEP 302

新导入钩子

PEP 328

导入:多行和绝对/相对

PEP 366

主模块显式相对导入

PEP 420

隐式命名空间包

PEP 451

导入系统的一个模块规范类型

PEP 488

消除PYO文件

PEP 489

多阶段扩展模块初始化

PEP 552

确定性的 pyc 文件

PEP 3120

使用 UTF-8 作为默认的源编码

PEP 3147

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 和其它关键模块。在很多例子中,扩展模块并不是设计为不止一次的初始化,并且当重新加载时,可能会以任意方式失败。

如果一个模块使用 fromimport … 导入的对象来自另外一个模块,给其它模块调用 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 版后已移除: 使用 MetaPathFinderPathEntryFinder 来代替。

  • abstractmethod find_module(fullname, path=None)

    为指定的模块查找 loader 定义的抽象方法。本来是在 PEP 302 指定的,这个方法是在 sys.meta_path 和基于路径的导入子系统中使用。

    在 3.4 版更改: 当被调用的时候,返回 None 而不是引发 NotImplementedError

    3.10 版后已移除: Implement MetaPathFinder.find_spec() or PathEntryFinder.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 concrete MetaPathFinders.

    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 concrete PathEntryFinders.

    3.4 新版功能.

  • find_loader(fullname)

    一个用于在模块中查找一个 loader 的遗留方法。 返回一个 (loader, portion) 的2元组,portion 是一个贡献给命名空间包部分的文件系统位置的序列。 加载器可能是 None,同时正在指定的 portion 表示的是贡献给命名空间包的文件系统位置。portion 可以使用一个空列表来表示加载器不是命名空间包的一部分。 如果 loaderNone 并且 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)

一个继承自 ResourceLoaderExecutionLoader,提供 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

一个用于实现源文件(和可选地字节码)加载的抽象基类。这个类继承自 ResourceLoaderExecutionLoader,需要实现:

  • 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 in sys.path_importer_cache, then sys.path_hooks is searched for a finder for the path entry and, if found, is stored in sys.path_importer_cache along with being queried about the module. If no finder is ever found then None 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 in sys.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 in sys.path_importer_cache that define the method. Otherwise entries in sys.path_importer_cache set to None are deleted.

    在 3.7 版更改: Entries of None in sys.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 of FileFinder 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 if path 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 from path.

  • 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 on EXTENSION_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 and ast.stmt subclasses have lineno, col_offset, end_lineno, and end_col_offset attributes. The lineno and end_lineno are the first and last line numbers of source text span (1-indexed so the first line is line 1) and the col_offset and end_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 a JoinedStr node representing the formatting of the value, or None if no format was specified. Both conversion and format_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 of keyword 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 both target and value 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 an arguments 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 and kwonlyargs are lists of arg nodes.
  • vararg and kwarg are single arg nodes, referring to the *args, **kwargs parameters.
  • kw_defaults is a list of default values for keyword-only arguments. If one is None, 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 name
  • bases is a list of nodes for explicitly specified base classes.
  • keywords is a list of keyword nodes, principally for ‘metaclass’. Other keywords will be passed to the metaclass, as per PEP-3115.
  • starargs and kwargs 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 in FunctionDef.
>>> 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 source return 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, or generic_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 with get_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 版更改: 补充 AWAITASYNC 标记。

在 3.7 版更改: 补充 COMMENTNLENCODING 标记。

在 3.7 版更改: 移除 AWAITASYNC 标记。 “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)

返回一个基于字典的树,其中包含与模块中每个用 defclass 语句定义的函数和类相对应的函数和类描述器。 被返回的字典会将模块层级的函数和类名映射到它们的描述器。 嵌套的对象会被输入到它们的上级子目录中。 与 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 所使用的值。

doraisequiet 参数确定在编译文件时如何处理错误。 如果 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) 三元组的序列。 opcodeOpcodeInfo 类的一个实例;arg 是 Python 对象形式的 opcode 参数的已解码值;pos 是 opcode 所在的位置。 pickle 可以是一个字符串或一个文件类对象。

pickletools.optimize(picklestring)

在消除未使用的 PUT 操作码之后返回一个新的等效 pickle 字符串。 优化后的 pickle 将更为简短,耗费更为的传输时间,要求更少的存储空间并能更高效地解封。

Windows系统相关模块

本章节叙述的模块只在 Windows 平台上可用。

Unix 专有服务

本章描述的模块提供了 Unix 操作系统独有特性的接口,在某些情况下也适用于它的某些或许多衍生版。 以下为模块概览:

被取代的模块

本章中描述的模块均已弃用,仅保留用于向后兼容。 它们已经被其他模块所取代。

未创建文档的模块

以下是应当记入文档但是目前尚无文档的模块速览列表。

本章的想法和原内容取自 Fredrik Lundh 的帖子;本章的具体内容已经大幅修改。

平台特定模块

这些模块用于实现 os.path 模块,除此之外没有文档。几乎没有必要创建这些文档。

ntpath

— 在 Win32 和 Win64 平台上实现 os.path

posixpath

— 在 POSIX 上实现 os.path

Security Considerations

The following modules have specific security considerations:


文章作者: 杰克成
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 杰克成 !
评论
  目录