Python 2.7 的新增功能 — Python 文档
Python 2.7 中的新功能
- 作者
- 是 Kuchling (amk at amk.ca)
本文解释了 Python 2.7 中的新功能。 Python 2.7 于 2010 年 7 月 3 日发布。
对于浮点数和 Decimal 类,数值处理在许多方面都得到了改进。 标准库中有一些有用的补充,例如大大增强的 unittest 模块、用于解析命令行选项的 argparse 模块、方便的 OrderedDict 和 [ collections 模块中的 X209X]Counter 类,以及许多其他改进。
Python 2.7 计划成为 2.x 版本中的最后一个,因此我们致力于使其成为长期的良好版本。 为了帮助移植到 Python 3,Python 3.x 系列的几个新功能已包含在 2.7 中。
本文不尝试提供新功能的完整规范,而是提供一个方便的概述。 有关完整详细信息,您应该参考 https://docs.python.org 上的 Python 2.7 文档。 如果您想了解设计和实现的基本原理,请参阅有关特定新功能的 PEP 或 https://bugs.python.org 上讨论更改的问题。 只要有可能,“Python 中的新功能”链接到每个更改的错误/补丁项。
Python 2.x 的未来
Python 2.7 是 2.x 系列中的最后一个主要版本,因为 Python 维护者已将其新功能开发工作的重点转移到 Python 3.x 系列。 这意味着,虽然 Python 2 继续接收错误修复,并进行更新以在新硬件和支持的操作系统版本上正确构建,但不会有新的语言或标准库的完整功能版本。
然而,虽然 Python 2.7 和 Python 3 之间有一个很大的公共子集,并且迁移到该公共子集或直接迁移到 Python 3 所涉及的许多更改可以安全地自动化,但一些其他更改(特别是与 Unicode 处理相关的更改) ) 可能需要仔细考虑,最好是强大的自动化回归测试套件,才能有效地迁移。
这意味着 Python 2.7 将保留很长时间,为尚未移植到 Python 3 的生产系统提供稳定且受支持的基础平台。 Python 2.7 系列的完整预期生命周期在 PEP 373 中有详细说明。
2.7 的长期意义的一些关键后果是:
- 如上所述,与早期的 2.x 版本相比,2.7 版本的维护期要长得多。 目前预计 Python 2.7 仍将得到核心开发团队的支持(接收安全更新和其他错误修复),至少要到 2020 年(首次发布后 10 年,相比之下,更典型的支持期为 18-24 个月)。
- 随着 Python 2.7 标准库的老化,对 Python 2 用户而言,有效使用 Python 包索引(直接或通过重新分发器)变得更加重要。 除了用于各种任务的各种第三方包外,可用的包还包括与 Python 2 兼容的 Python 3 标准库中新模块和功能的向后移植,以及各种工具和库,这些工具和库可以使其更容易迁移到 Python 3。 Python Packaging User Guide 提供了从 Python Package Index 下载和安装软件的指南。
- 虽然现在增强 Python 2 的首选方法是在 Python 包索引上发布新包,但这种方法不一定适用于所有情况,尤其是与网络安全相关的情况。 在无法通过在 PyPI 上发布新的或更新的包来充分处理的特殊情况下,Python 增强提案过程可用于为直接向 Python 2 标准库添加新功能提供理由。 任何此类添加以及添加它们的维护版本将在下面的 添加到 Python 2.7 维护版本 的新功能部分中注明。
对于希望从 Python 2 迁移到 Python 3 的项目,或者对于希望支持 Python 2 和 Python 3 用户的库和框架开发人员,有多种工具和指南可用于帮助决定合适的方法并管理一些所涉及的技术细节。 推荐的起点是 Porting Python 2 Code to Python 3 HOWTO 指南。
对弃用警告处理的更改
对于 Python 2.7,已做出策略决定,默认情况下仅对开发人员感兴趣的警告静音。 DeprecationWarning 及其后代现在被忽略,除非另有要求,防止用户看到由应用程序触发的警告。 此更改也在成为 Python 3.2 的分支中进行。 (在 stdlib-sig 上讨论并在 :issue:`7319` 中执行。)
在以前的版本中,DeprecationWarning 消息默认启用,为 Python 开发人员提供明确的指示,说明他们的代码在 Python 的未来主要版本中可能会在哪里中断。
但是,越来越多的基于 Python 的应用程序用户并未直接参与这些应用程序的开发。 DeprecationWarning 消息与此类用户无关,使他们担心应用程序实际上是否正常工作,并增加了应用程序开发人员应对这些问题的负担。
您可以通过使用 -Wdefault(简称:-Wd)开关运行 Python,或通过设置 来重新启用 DeprecationWarning 消息的显示在运行 Python 之前将 PYTHONWARNINGS 环境变量设置为 "default"
(或 "d"
)。 Python 代码也可以通过调用 warnings.simplefilter('default')
重新启用它们。
unittest
模块还会在运行测试时自动重新启用弃用警告。
Python 3.1 特性
就像 Python 2.6 合并了 Python 3.0 的功能一样,2.7 版合并了 Python 3.1 中的一些新功能。 2.x 系列继续提供迁移到 3.x 系列的工具。
向后移植到 2.7 的 3.1 功能的部分列表:
- 集合文字的语法(
{1,2,3}
是可变集合)。 - 字典和集合推导(
{i: i*2 for i in range(3)}
)。 - 单个 with 语句中的多个上下文管理器。
- io 库的新版本,用 C 重写以提高性能。
- PEP 372: Add an Ordered Dictionary to collections 中描述的有序字典类型。
- PEP 378: 千位分隔符的格式说明符 中描述的新
","
格式说明符。 - memoryview 对象。
- importlib 模块的一个小子集, 描述如下 。
- 在许多情况下,浮点数
x
的 repr() 更短:它现在基于最短的十进制字符串,保证四舍五入为x
。 与以前版本的 Python 一样,保证float(repr(x))
恢复x
。 - 浮点数到字符串和字符串到浮点数的转换正确四舍五入。 round() 函数现在也已正确舍入。
- PyCapsule 类型,用于为扩展模块提供 C API。
- PyLong_AsLongAndOverflow() C API 函数。
其他新的 Python3 模式警告包括:
operator.isCallable()
和operator.sequenceIncludes()
在 3.x 中不受支持,现在会触发警告。-3
开关现在会自动启用-Qwarn
开关,该开关会导致有关对整数和长整数使用经典除法的警告。
PEP 372:向集合添加有序字典
常规 Python 字典以任意顺序迭代键/值对。 多年来,许多作者编写了替代实现来记住密钥最初插入的顺序。 基于这些实现的经验,2.7 在 collections 模块中引入了一个新的 OrderedDict 类。
OrderedDict API 提供与常规字典相同的接口,但根据第一次插入键的时间以有保证的顺序迭代键和值:
>>> from collections import OrderedDict
>>> d = OrderedDict([('first', 1),
... ('second', 2),
... ('third', 3)])
>>> d.items()
[('first', 1), ('second', 2), ('third', 3)]
如果新条目覆盖现有条目,则原始插入位置保持不变:
>>> d['second'] = 4
>>> d.items()
[('first', 1), ('second', 4), ('third', 3)]
删除一个条目并重新插入它会将它移到最后:
>>> del d['second']
>>> d['second'] = 5
>>> d.items()
[('first', 1), ('third', 3), ('second', 5)]
popitem() 方法有一个可选的 last 参数,默认为 True
。 如果 last 为真,则返回并删除最近添加的键; 如果为 false,则选择最旧的键:
>>> od = OrderedDict([(x,0) for x in range(20)])
>>> od.popitem()
(19, 0)
>>> od.popitem()
(18, 0)
>>> od.popitem(last=False)
(0, 0)
>>> od.popitem(last=False)
(1, 0)
比较两个有序字典会检查键和值,并要求插入顺序相同:
>>> od1 = OrderedDict([('first', 1),
... ('second', 2),
... ('third', 3)])
>>> od2 = OrderedDict([('third', 3),
... ('first', 1),
... ('second', 2)])
>>> od1 == od2
False
>>> # Move 'third' key to the end
>>> del od2['third']; od2['third'] = 3
>>> od1 == od2
True
将 OrderedDict 与常规字典进行比较会忽略插入顺序,只比较键和值。
OrderedDict 如何工作? 它维护一个双向链接的键列表,在插入新键时将它们附加到列表中。 二级字典将键映射到它们对应的列表节点,因此删除不必遍历整个链表,因此保持 O(1)。
标准库现在支持在多个模块中使用有序字典。
ConfigParser
模块默认使用它们,这意味着现在可以读取、修改配置文件,然后按其原始顺序写回。- collections.namedtuple() 的 _asdict() 方法现在返回一个有序字典,其中的值与底层元组索引的出现顺序相同。
- json 模块的 JSONDecoder 类构造函数使用 object_pairs_hook 参数进行扩展,以允许解码器构建
OrderedDict
实例。 还添加了对 PyYAML 等第三方工具的支持。
PEP 378:千位分隔符的格式说明符
为了使程序输出更具可读性,为大数添加分隔符会很有用,将它们呈现为 18,446,744,073,709,551,616 而不是 18446744073709551616。
这样做的完全通用的解决方案是 locale 模块,它可以使用不同的分隔符(“,”在北美,“.”在欧洲)和不同的分组大小,但 locale使用起来很复杂,不适合多线程应用程序,其中不同的线程为不同的语言环境生成输出。
因此,在 str.format() 方法使用的迷你语言中添加了一个简单的逗号分组机制。 格式化浮点数时,只需在宽度和精度之间包含一个逗号:
>>> '{:20,.2f}'.format(18446744073709551616.0)
'18,446,744,073,709,551,616.00'
格式化整数时,请在宽度后包含逗号:
>>> '{:20,d}'.format(18446744073709551616)
'18,446,744,073,709,551,616'
这种机制根本不适应; 逗号始终用作分隔符,并且分组始终为三位数。 逗号格式机制不像 locale 模块那样通用,但更易于使用。
PEP 389:用于解析命令行的 argparse 模块
添加了用于解析命令行参数的 argparse 模块,作为 optparse 模块的更强大替代品。
这意味着 Python 现在支持三种不同的模块来解析命令行参数:getopt、optparse 和 argparse。 getopt 模块与 C 库的 getopt()
函数非常相似,因此如果您正在编写最终将用 C 重写的 Python 原型,它仍然很有用。 optparse 变得多余,但没有计划将其删除,因为有许多脚本仍在使用它,并且没有自动更新这些脚本的方法。 (讨论了使 argparse API 与 optparse 的接口一致,但由于过于混乱和困难而被拒绝。)
简而言之,如果您正在编写新脚本并且不需要担心与早期版本的 Python 的兼容性,请使用 argparse 而不是 optparse。
下面是一个例子:
import argparse
parser = argparse.ArgumentParser(description='Command-line example.')
# Add optional switches
parser.add_argument('-v', action='store_true', dest='is_verbose',
help='produce verbose output')
parser.add_argument('-o', action='store', dest='output',
metavar='FILE',
help='direct output to FILE instead of stdout')
parser.add_argument('-C', action='store', type=int, dest='context',
metavar='NUM', default=0,
help='display NUM lines of added context')
# Allow any number of additional arguments.
parser.add_argument(nargs='*', action='store', dest='inputs',
help='input filenames (default is stdin)')
args = parser.parse_args()
print args.__dict__
除非你覆盖它,-h
和 --help
开关会自动添加,并产生整齐格式化的输出:
-> ./python.exe argparse-example.py --help
usage: argparse-example.py [-h] [-v] [-o FILE] [-C NUM] [inputs [inputs ...]]
Command-line example.
positional arguments:
inputs input filenames (default is stdin)
optional arguments:
-h, --help show this help message and exit
-v produce verbose output
-o FILE direct output to FILE instead of stdout
-C NUM display NUM lines of added context
与 optparse 一样,命令行开关和参数作为具有由 dest 参数命名的属性的对象返回:
-> ./python.exe argparse-example.py -v
{'output': None,
'is_verbose': True,
'context': 0,
'inputs': []}
-> ./python.exe argparse-example.py -v -o /tmp/output -C 4 file1 file2
{'output': '/tmp/output',
'is_verbose': True,
'context': 4,
'inputs': ['file1', 'file2']}
argparse 比 optparse 有更高级的验证; 您可以通过传递 '*'
指定 0 个或多个参数,通过传递 '+'
指定 1 个或多个参数,或使用 '?'
指定一个可选参数。 顶级解析器可以包含子解析器来定义具有不同开关集的子命令,如 svn commit
、svn checkout
等。 您可以将参数的类型指定为 FileType,它会自动为您打开文件并理解 '-'
表示标准输入或输出。
也可以看看
- argparse 文档
- argparse 模块的文档页面。
- 升级 optparse 代码
- Python 文档的一部分,描述了如何转换使用 optparse 的代码。
- PEP 389 - argparse - 新的命令行解析模块
- PEP 由 Steven Bethard 编写和实施。
PEP 391:基于字典的日志配置
logging 模块非常灵活; 应用程序可以定义一个日志子系统树,这个树中的每个记录器可以过滤掉某些消息,以不同的方式格式化它们,并将消息定向到不同数量的处理程序。
所有这些灵活性都需要大量配置。 您可以编写 Python 语句来创建对象并设置它们的属性,但复杂的设置需要冗长而乏味的代码。 logging也支持解析文件的fileConfig()
函数,但是文件格式不支持配置过滤器,程序生成比较麻烦。
Python 2.7 添加了一个 dictConfig()
函数,该函数使用字典来配置日志记录。 从不同来源生成字典的方法有很多种:用代码构建一个; 解析包含 JSON 的文件; 或者使用 YAML 解析库(如果已安装)。 有关更多信息,请参阅 配置功能 。
以下示例配置了两个记录器,根记录器和名为“network”的记录器。 发送到根记录器的消息将使用 syslog 协议发送到系统日志,而发送到“网络”记录器的消息将写入 network.log
文件,一旦日志达到 1MB,该文件将被轮换。
import logging
import logging.config
configdict = {
'version': 1, # Configuration schema in use; must be 1 for now
'formatters': {
'standard': {
'format': ('%(asctime)s %(name)-15s '
'%(levelname)-8s %(message)s')}},
'handlers': {'netlog': {'backupCount': 10,
'class': 'logging.handlers.RotatingFileHandler',
'filename': '/logs/network.log',
'formatter': 'standard',
'level': 'INFO',
'maxBytes': 1000000},
'syslog': {'class': 'logging.handlers.SysLogHandler',
'formatter': 'standard',
'level': 'ERROR'}},
# Specify all the subordinate loggers
'loggers': {
'network': {
'handlers': ['netlog']
}
},
# Specify properties of the root logger
'root': {
'handlers': ['syslog']
},
}
# Set up configuration
logging.config.dictConfig(configdict)
# As an example, log two error messages
logger = logging.getLogger('/')
logger.error('Database not found')
netlogger = logging.getLogger('network')
netlogger.error('Connection failed')
logging 模块的三个较小的增强,全部由 Vinay Sajip 实现,是:
- SysLogHandler 类现在支持通过 TCP 进行系统日志记录。 构造函数有一个 socktype 参数给出要使用的套接字类型,socket.SOCK_DGRAM 用于 UDP 或 socket.SOCK_STREAM 用于 TCP。 默认协议仍然是 UDP。
- Logger 实例获得了 getChild() 方法,该方法使用相对路径检索后代记录器。 例如,一旦您通过执行
log = getLogger('app')
检索记录器,调用log.getChild('network.listen')
等效于getLogger('app.network.listen')
。 - LoggerAdapter 类获得了一个
isEnabledFor()
方法,该方法采用 级别 并返回底层记录器是否会处理该重要性级别的消息。
PEP 3106:字典视图
字典方法 keys()、values() 和 items() 在 Python 3.x 中是不同的。 它们返回一个名为 view 的对象,而不是一个完全物化的列表。
在 Python 2.7 中无法更改 keys()、values() 和 items() 的返回值,因为太多代码会被破坏。 而是以新名称 viewkeys()
、viewvalues()
和 viewitems()
添加了 3.x 版本。
>>> d = dict((i*10, chr(65+i)) for i in range(26))
>>> d
{0: 'A', 130: 'N', 10: 'B', 140: 'O', 20: ..., 250: 'Z'}
>>> d.viewkeys()
dict_keys([0, 130, 10, 140, 20, 150, 30, ..., 250])
视图可以迭代,但键和项目视图也表现得像集合。 &
运算符执行交集,|
执行并集:
>>> d1 = dict((i*10, chr(65+i)) for i in range(26))
>>> d2 = dict((i**.5, i) for i in range(1000))
>>> d1.viewkeys() & d2.viewkeys()
set([0.0, 10.0, 20.0, 30.0])
>>> d1.viewkeys() | range(0, 30)
set([0, 1, 130, 3, 4, 5, 6, ..., 120, 250])
该视图跟踪字典及其内容随着字典的修改而变化:
>>> vk = d.viewkeys()
>>> vk
dict_keys([0, 130, 10, ..., 250])
>>> d[260] = '&'
>>> vk
dict_keys([0, 130, 260, 10, ..., 250])
但是,请注意,在迭代视图时不能添加或删除键:
>>> for k in vk:
... d[k*2] = k
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: dictionary changed size during iteration
您可以使用 Python 2.x 代码中的视图方法,2to3 转换器会将它们更改为标准的 keys()、values() 和 items() 方法。
也可以看看
- PEP 3106 - 修改 dict.keys()、.values() 和 .items()
- 由 Guido van Rossum 编写的 PEP。 由 Alexandre Vassalotti 向后移植到 2.7; :问题:`1967`。
PEP 3137:memoryview 对象
memoryview 对象提供了与 bytes 类型的接口匹配的另一个对象的内存内容的视图。
>>> import string
>>> m = memoryview(string.letters)
>>> m
<memory at 0x37f850>
>>> len(m) # Returns length of underlying object
52
>>> m[0], m[25], m[26] # Indexing returns one byte
('a', 'z', 'A')
>>> m2 = m[0:26] # Slicing returns another memoryview
>>> m2
<memory at 0x37f080>
视图的内容可以转换为字节字符串或整数列表:
>>> m2.tobytes()
'abcdefghijklmnopqrstuvwxyz'
>>> m2.tolist()
[97, 98, 99, 100, 101, 102, 103, ... 121, 122]
>>>
memoryview 对象允许修改底层对象,如果它是一个可变对象。
>>> m2[0] = 75
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot modify read-only memory
>>> b = bytearray(string.letters) # Creating a mutable object
>>> b
bytearray(b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
>>> mb = memoryview(b)
>>> mb[0] = '*' # Assign to view, changing the bytearray.
>>> b[0:5] # The bytearray has been changed.
bytearray(b'*bcde')
>>>
也可以看看
- PEP 3137 - 不可变字节和可变缓冲区
- 由 Guido van Rossum 编写的 PEP。 由 Travis Oliphant、Antoine Pitrou 和其他人实施。 由 Antoine Pitrou 向后移植到 2.7; :问题:`2396`。
其他语言更改
对核心 Python 语言进行的一些较小更改是:
集合文字的语法已从 Python 3.x 向后移植。 大括号用于包围结果可变集的内容; 集合文字与字典的区别在于不包含冒号和值。
{}
继续代表空字典; 使用set()
作为空集。>>> {1, 2, 3, 4, 5} set([1, 2, 3, 4, 5]) >>> set() # empty set set([]) >>> {} # empty dict {}
由 Alexandre Vassalotti 反向移植; :问题:`2335`。
字典和集合推导是从 3.x 向后移植的另一个功能,将列表/生成器推导概括为使用集合和字典的文字语法。
>>> {x: x*x for x in range(6)} {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25} >>> {('a'*x) for x in range(6)} set(['', 'a', 'aa', 'aaa', 'aaaa', 'aaaaa'])
由 Alexandre Vassalotti 反向移植; :问题:`2333`。
with 语句现在可以在一个语句中使用多个上下文管理器。 上下文管理器从左到右处理,每个都被视为开始一个新的
with
语句。 这意味着:with A() as a, B() as b: ... suite of statements ...
相当于:
with A() as a: with B() as b: ... suite of statements ...
contextlib.nested()
函数提供了一个非常相似的函数,因此不再需要它并已被弃用。(在 https://codereview.appspot.com/53094 中提出;由 Georg Brandl 实现。)
浮点数和字符串之间的转换现在可以在大多数平台上正确四舍五入。 这些转换发生在许多不同的地方: str() 在浮点数和复数上; float 和 complex 构造函数; 数字格式; 使用 marshal、pickle 和 json 模块序列化和反序列化浮点数和复数; 解析 Python 代码中的浮点数和虚数; 和 十进制 到浮点数的转换。
与此相关的是,浮点数 x 的 repr() 现在返回基于最短十进制字符串的结果,该字符串保证四舍五入为 x在正确舍入下(使用舍入半到偶数舍入模式)。 以前它给出了一个基于将 x 舍入为 17 位十进制数字的字符串。
负责此改进的舍入库可在 Windows 和使用 gcc、icc 或 suncc 编译器的 Unix 平台上运行。 可能有少数平台无法保证此代码的正确运行,因此该代码不在此类系统上使用。 您可以通过检查 sys.float_repr_style 找出正在使用的代码,如果新代码正在使用,则为
short
,否则为legacy
。由 Eric Smith 和 Mark Dickinson 实现,使用 David Gay 的
dtoa.c
库; :问题:`7117`。从长整数和常规整数到浮点数的转换现在以不同的方式舍入,返回最接近数字的浮点数。 这对于可以精确转换的小整数无关紧要,但对于不可避免地会失去精度的大数,Python 2.7 现在更接近地近似了。 例如,Python 2.6 计算如下:
>>> n = 295147905179352891391 >>> float(n) 2.9514790517935283e+20 >>> n - long(float(n)) 65535L
Python 2.7 的浮点结果更大,但更接近真实值:
>>> n = 295147905179352891391 >>> float(n) 2.9514790517935289e+20 >>> n - long(float(n)) -1L
(由 Mark Dickinson 实施;:issue:`3166`。)
整数除法的舍入行为也更准确。 (也由 Mark Dickinson 实现;:issue:`1811`。)
删除了对复数的隐式强制转换; 解释器将不再尝试在复杂对象上调用
__coerce__()
方法。 (由 Meador Inge 和 Mark Dickinson 删除;:issue:`5211`。)str.format() 方法现在支持替换字段的自动编号。 这使得使用 str.format() 更类似于使用
%s
格式:>>> '{}:{}:{}'.format(2009, 04, 'Sunday') '2009:4:Sunday' >>> '{}:{}:{day}'.format(2009, 4, day='Sunday') '2009:4:Sunday'
自动编号从左到右取字段,因此第一个
{...}
说明符将使用 str.format() 的第一个参数,下一个说明符将使用下一个参数,以及很快。 您不能混合自动编号和显式编号——要么对所有的说明符字段编号,要么不编号——但您可以混合自动编号和命名字段,如上面的第二个示例。 (由 Eric Smith 提供;:issue:`5237`。)复数现在正确支持使用 format(),并且默认为右对齐。 指定精度或逗号分隔适用于数字的实部和虚部,但指定的字段宽度和对齐方式适用于整个结果
1.5+3j
输出。 (由 Eric Smith 提供;:issue:`1588` 和 :issue:`7988`。)'F' 格式代码现在总是使用大写字符格式化其输出,因此它现在将生成 'INF' 和 'NAN'。 (由 Eric Smith 提供;:issue:`3382`。)
低级更改:object.__format__() 方法现在在传递格式字符串时触发 PendingDeprecationWarning,因为 对象的
__format__()
方法 将对象转换为字符串表示形式并对其进行格式化。 以前,该方法会默默地将格式字符串应用于字符串表示,但这可能会隐藏 Python 代码中的错误。 如果您提供格式信息,例如对齐或精度,大概您希望以某种特定于对象的方式应用格式。 (由 Eric Smith 修正;:问题:`7994`。)int() 和
long()
类型获得了一个bit_length
方法,该方法返回以二进制表示其参数所需的位数:>>> n = 37 >>> bin(n) '0b100101' >>> n.bit_length() 6 >>> n = 2**123-1 >>> n.bit_length() 123 >>> (n+1).bit_length() 124
(由 Fredrik Johansson 和 Victor Stinner 提供;:issue:`3439`。)
import 语句将不再尝试绝对导入如果相对导入(例如
from .os import sep
) 失败。 这修复了一个错误,但可能会破坏某些仅偶然工作的import
语句。 (由 Meador Inge 修复;:问题:`7902`。)现在,内置
unicode
类型的子类可以覆盖__unicode__()
方法。 (由 Victor Stinner 实施;:issue:`1583863`。)bytearray 类型的 translate() 方法现在接受
None
作为它的第一个参数。 (由 Georg Brandl 修复;:问题:`4759`。)当使用
@classmethod
和@staticmethod
将方法包装为类或静态方法时,包装对象现在将包装的函数公开为其__func__
属性。 (根据 George Sakkis 的建议,由 Amaury Forgeot d'Arc 提供;:issue:`5982`。)当使用
__slots__
设置一组受限制的属性时,删除未设置的属性不会像您预期的那样引发 AttributeError。 由本杰明·彼得森修复; :问题:`7604`。)现在支持两种新编码:“cp720”,主要用于阿拉伯文本; 和“cp858”,CP 850 的变体,添加了欧元符号。 (CP720 由 Alexander Belchenko 和 Amaury Forgeot d'Arc 在 :issue:`1616979` 贡献;CP858 由 Tim Hatch 在 :issue:`8016` 贡献。)
当尝试在 POSIX 平台上打开目录时,
file
对象现在将在 IOError 异常上设置filename
属性(Jan Kaliszewski 指出;:问题: `4764`),现在明确检查并禁止写入只读文件对象,而不是信任 C 库来捕获和报告错误(由 Stefan Krah 修复;:issue:`5677`[ X375X])。Python 标记器现在自己翻译行尾,因此 compile() 内置函数现在接受使用任何行尾约定的代码。 此外,它不再要求代码以换行符结尾。
在 Python 3.x 中,函数定义中的额外括号是非法的,这意味着您会收到来自
def f((x)): pass
的语法错误。 在 Python3 警告模式下,Python 2.7 现在会警告这种奇怪的用法。 (James Lingard 指出;:issue:`7362`。)现在可以创建对旧式类对象的弱引用。 新式类总是弱引用的。 (由 Antoine Pitrou 修复;:问题:`8268`。)
当模块对象被垃圾收集时,模块的字典现在只有在没有其他人持有对字典的引用时才会被清除 (:issue:`7140`)。
口译员变化
一个新的环境变量 PYTHONWARNINGS 允许控制警告。 它应该设置为包含警告设置的字符串,等同于与 -W 开关一起使用的设置,用逗号分隔。 (由 Brian Curtin 提供;:issue:`7301`。)
例如,以下设置每次发生时都会打印警告,但会将来自 Cookie
模块的警告转换为错误。 (设置环境变量的确切语法因操作系统和外壳而异。)
export PYTHONWARNINGS=all,error:::Cookie:0
优化
添加了多项性能增强功能:
添加了一个新的操作码来执行 with 语句的初始设置,查找
__enter__()
和__exit__()
方法。 (本杰明·彼得森供稿。)对于一种常见的使用模式,垃圾收集器现在表现得更好:当许多对象被分配而没有释放它们中的任何一个时。 以前这需要二次垃圾收集时间,但现在随着堆上对象数量的增加,完全垃圾收集的数量减少了。 新逻辑只在中间代被回收 10 次并且中间代的幸存者对象数量超过最老一代对象数量的 10% of 时才执行完整的垃圾回收传递。 (由 Martin von Löwis 提出并由 Antoine Pitrou 实施;:issue:`4074`。)
垃圾收集器试图避免跟踪不能成为循环一部分的简单容器。 在 Python 2.7 中,对于包含原子类型(例如整数、字符串等)的元组和字典,现在是这样。 传递性地,也不会跟踪包含原子类型元组的 dict。 这有助于通过减少收集器要考虑和遍历的对象数量来降低每次垃圾收集的成本。 (由 Antoine Pitrou 提供;:issue:`4688`。)
长整数现在内部存储在基数 2**15 或基数 2**30 中,基数在构建时确定。 以前,它们总是存储在基数 2**15 中。 使用基数 2**30 在 64 位机器上有显着的性能改进,但在 32 位机器上的基准测试结果好坏参半。 因此,默认是在 64 位机器上使用 base 2**30,在 32 位机器上使用 base 2**15; 在 Unix 上,有一个新的配置选项
--enable-big-digits
可用于覆盖此默认值。除了性能改进之外,最终用户应该看不到这种变化,但有一个例外:为了测试和调试目的,有一个新的 structseq
sys.long_info
提供有关内部格式的信息,给出每位数的位数和用于存储每个数字的 C 类型的大小(以字节为单位):>>> import sys >>> sys.long_info sys.long_info(bits_per_digit=30, sizeof_digit=4)
(由 Mark Dickinson 提供;:issue:`4258`。)
另一组更改使长对象小了几个字节:在 32 位系统上小了 2 个字节,在 64 位系统上小了 6 个字节。 (由 Mark Dickinson 提供;:issue:`5260`。)
通过收紧内部循环、执行移位而不是乘法以及修复不必要的额外迭代,长整数的除法算法变得更快。 各种基准测试显示,长整数除法和模运算的速度提高了 50% 到 150%。 (由 Mark Dickinson 提供;:issue:`5512`。)按位运算也明显更快(Gregory Smith 的初始补丁;:issue:`1087418`)。
%
的实现检查左侧操作数是否为 Python 字符串并对其进行特殊处理; 这导致经常将%
与字符串一起使用的应用程序(例如模板库)的性能提高了 1-3%。 (由 Collin Winter 实施;:issue:`5176`。)具有
if
条件的列表推导式被编译成更快的字节码。 (Antoine Pitrou 的补丁,Jeffrey Yasskin 向后移植到 2.7;:问题:`4715`。)将整数或长整数转换为十进制字符串的速度通过特殊大小写的基数 10 而不是使用支持任意基数的通用转换函数。 (高文博尔顿的补丁;:问题:`6713`。)
字符串类型(字符串、Unicode 字符串和 [ X122X]bytearray 对象)现在使用快速反向搜索算法而不是逐字符扫描。 这有时会快 10 倍。 (由 Florent Xicluna 添加;:issue:`7462` 和 :issue:`7622`。)
pickle 和
cPickle
模块现在会自动对用于属性名称的字符串进行实习,从而减少因 unpickling 产生的对象的内存使用量。 (由 Jake McGuire 提供;:issue:`5084`。)cPickle
模块现在对字典进行特殊处理,将它们腌制所需的时间几乎减半。 (由 Collin Winter 提供;:问题:`5670`。)
新的和改进的模块
在每个版本中,Python 的标准库都获得了许多增强功能和错误修复。 这是最显着更改的部分列表,按模块名称的字母顺序排序。 查阅源代码树中的 Misc/NEWS
文件以获取更完整的更改列表,或查看 Subversion 日志以获取所有详细信息。
bdb 模块的基础调试类 Bdb 获得了跳过模块的功能。 构造函数现在采用包含全局样式模式的可迭代对象,例如
django.*
; 调试器不会从匹配这些模式之一的模块进入堆栈帧。 (在 Senthil Kumaran 的建议下由 Maru Newby 提供;:issue:`5142`。)binascii 模块现在支持缓冲区 API,因此它可以与 memoryview 实例和其他类似的缓冲区对象一起使用。 (由 Florent Xicluna 从 3.x 向后移植;:问题:`7703`。)
更新模块:
bsddb
模块已从4.7.2devel9更新到pybsddb包的4.8.4版本。 新版本具有更好的 Python 3.x 兼容性、各种错误修复,并添加了几个新的 BerkeleyDB 标志和方法。 (由 Jesús Cea Avión 更新;:issue:`8156`。 pybsddb 更改日志可以在 http://hg.jcea.es/pybsddb/file/tip/ChangeLog 处读取。)bz2 模块的 BZ2File 现在支持上下文管理协议,因此您可以编写
with bz2.BZ2File(...) as f:
。 (由 Hagen Fürstenau 提供;:issue:`3860`。)新类:collections 模块中的 Counter 类可用于统计数据。 Counter 实例的行为大多类似于字典,但对于丢失的键返回零,而不是引发 KeyError:
>>> from collections import Counter >>> c = Counter() >>> for letter in 'here is a sample of english text': ... c[letter] += 1 ... >>> c Counter({' ': 6, 'e': 5, 's': 3, 'a': 2, 'i': 2, 'h': 2, 'l': 2, 't': 2, 'g': 1, 'f': 1, 'm': 1, 'o': 1, 'n': 1, 'p': 1, 'r': 1, 'x': 1}) >>> c['e'] 5 >>> c['z'] 0
还有三个额外的 Counter 方法。 most_common() 返回 N 个最常见的元素及其计数。 elements() 返回包含元素的迭代器,重复每个元素的次数与其计数相同。 subtract() 取一个可迭代对象并为每个元素减去一个而不是添加; 如果参数是字典或另一个
Counter
,则减去计数。>>> c.most_common(5) [(' ', 6), ('e', 5), ('s', 3), ('a', 2), ('i', 2)] >>> c.elements() -> 'a', 'a', ' ', ' ', ' ', ' ', ' ', ' ', 'e', 'e', 'e', 'e', 'e', 'g', 'f', 'i', 'i', 'h', 'h', 'm', 'l', 'l', 'o', 'n', 'p', 's', 's', 's', 'r', 't', 't', 'x' >>> c['e'] 5 >>> c.subtract('very heavy on the letter e') >>> c['e'] # Count is now lower -1
由 Raymond Hettinger 提供; :问题:`1696199`。
新类:OrderedDict 在前面的部分 PEP 372:将有序字典添加到集合 中进行了描述。
新方法:deque 数据类型现在有一个 count() 方法,该方法返回等于提供的参数 x 和一个 的包含元素的数量]reverse() 方法就地反转双端队列的元素。 deque 还将其最大长度公开为只读 maxlen 属性。 (这两个功能都是由 Raymond Hettinger 添加的。)
namedtuple 类现在有一个可选的 rename 参数。 如果 rename 为 true,则由于重复或不合法的 Python 标识符而无效的字段名称将重命名为从字段列表中的字段位置派生的合法名称:
>>> from collections import namedtuple >>> T = namedtuple('T', ['field1', '$illegal', 'for', 'field2'], rename=True) >>> T._fields ('field1', '_1', '_2', 'field2')
(由 Raymond Hettinger 添加;:issue:`1818`。)
最后,如果将映射与不是
Mapping
的另一种类型进行比较,Mapping
抽象基类现在返回 NotImplemented。 (由 Daniel Stutzbach 修复;:问题:`8729`。)ConfigParser
模块中解析类的构造函数现在采用 allow_no_value 参数,默认为 false; 如果为 true,将允许没有值的选项。 例如:>>> import ConfigParser, StringIO >>> sample_config = """ ... [mysqld] ... user = mysql ... pid-file = /var/run/mysqld/mysqld.pid ... skip-bdb ... """ >>> config = ConfigParser.RawConfigParser(allow_no_value=True) >>> config.readfp(StringIO.StringIO(sample_config)) >>> config.get('mysqld', 'user') 'mysql' >>> print config.get('mysqld', 'skip-bdb') None >>> print config.get('mysqld', 'unknown') Traceback (most recent call last): ... NoOptionError: No option 'unknown' in section: 'mysqld'
(由 Mats Kindahl 提供;:issue:`7005`。)
不推荐使用的功能:
contextlib.nested()
允许使用单个 with 语句处理多个上下文管理器,已被弃用,因为with
语句现在支持多个上下文管理器。cookielib
模块现在忽略具有无效版本字段的 cookie,该字段不包含整数值。 (由约翰 J. 李; :问题:`3924`。)copy 模块的 deepcopy() 函数现在将正确复制绑定实例方法。 (由 Robert Collins 实施;:issue:`1515`。)
ctypes 模块现在总是将
None
转换为 CNULL
指针,用于声明为指针的参数。 (由 Thomas Heller 更改;:issue:`4606`。)底层 libffi 库 已更新至 3.0.9 版,包含针对不同平台的各种修复。 (由 Matthias Klose 更新;:issue:`8142`。)新方法:datetime 模块的 timedelta 类获得了一个 total_seconds() 方法,该方法返回持续时间的秒数。 (由 Brian Quinlan 提供;:issue:`5788`。)
新方法:Decimal 类获得了一个 from_float() 类方法,该方法执行浮点数到 Decimal 的精确转换。 这种精确转换力求与浮点表示值最接近的十进制近似值; 因此,结果的十进制值仍将包括不准确度(如果有)。 例如,
Decimal.from_float(0.1)
返回Decimal('0.1000000000000000055511151231257827021181583404541015625')
。 (由 Raymond Hettinger 实施;:issue:`4796`。)将 Decimal 的实例与浮点数进行比较现在可以根据操作数的数值产生合理的结果。 以前这样的比较会回退到 Python 比较对象的默认规则,它会根据对象的类型产生任意结果。 请注意,您仍然不能在其他运算(例如加法)中组合
Decimal
和浮点数,因为您应该明确选择如何在浮点数和 Decimal 之间进行转换。 (由 Mark Dickinson 修复;:问题:`2531`。)Decimal 的构造函数现在接受浮点数(由 Raymond Hettinger 添加;:issue:`8257`)和非欧洲 Unicode 字符,例如阿拉伯-印度数字(由马克狄金森;:问题:`6595`)。
Context 类的大多数方法现在接受整数以及 Decimal 实例; 唯一的例外是 canonical() 和 is_canonical() 方法。 (胡安·何塞·孔蒂的补丁;:问题:`7633`。)
当将 Decimal 实例与字符串的 format() 方法一起使用时,默认对齐方式以前是左对齐方式。 这已更改为右对齐,这对于数字类型更合理。 (由 Mark Dickinson 更改;:issue:`6857`。)
涉及信号 NaN 值(或
sNAN
)的比较现在发出信号InvalidOperation
,而不是根据比较运算符静默返回真或假值。 Quiet NaN 值(或NaN
)现在是可散列的。 (由 Mark Dickinson 修复;:问题:`7279`。)difflib 模块现在通过一个小的更改生成与现代 diff/patch 工具更兼容的输出,使用制表符代替空格作为分隔符给出文件名的标题。 (由 Anatoly Techtonik 修复;:问题:`7585`。)
Distutils
sdist
命令现在总是重新生成MANIFEST
文件,因为即使MANIFEST.in
或setup.py
文件没有被修改,用户可能已经创建一些应该包含的新文件。 (由 Tarek Ziadé 修复;:问题:`8688`。)doctest 模块的
IGNORE_EXCEPTION_DETAIL
标志现在将忽略包含正在测试的异常的模块的名称。 (Lennart Regebro 的补丁;:问题:`7490`。)email 模块的 Message 类现在将接受 Unicode 值有效负载,自动将有效负载转换为
output_charset
指定的编码。 (由 R. 大卫·默里; :问题:`1368247`。)Fraction 类现在接受单个浮点数或 Decimal 实例,或两个有理数,作为其构造函数的参数。 (由 Mark Dickinson 实现;在 :issue:`5812` 中添加了有理数,在 :issue:`8294` 中添加了浮点数/十进制数。)
分数和复数之间的排序比较(
<
、<=
、>
、>=
)现在会引发 TypeError。 这修复了一个疏忽,使 Fraction 与其他数字类型匹配。新类:ftplib 模块中的 FTP_TLS 使用 TLS 封装身份验证以及后续控制和数据传输提供安全的 FTP 连接。 (由 Giampaolo Rodola 提供;:issue:`2054`。)
由于添加了 rest 参数,用于二进制上传的 storbinary() 方法现在可以重新启动上传(Pablo Mouzo 的补丁;:issue:`6845`。)
新的类装饰器:functools 模块中的 total_ordering() 采用一个定义
__eq__()
方法和__lt__()
、[ X153X]、__gt__()
或__ge__()
,并生成缺失的比较方法。 由于__cmp__()
方法在 Python 3.x 中已被弃用,此装饰器使定义有序类变得更加容易。 (由 Raymond Hettinger 添加;:issue:`5479`。)新函数:cmp_to_key() 将采用旧式比较函数,该函数需要两个参数并返回一个新的可调用对象,该函数可用作 key 等函数的参数,例如 sorted()、min() 和 max() 等。 主要用途是帮助使代码与 Python 3.x 兼容。 (由 Raymond Hettinger 添加。)
新函数:gc 模块的 is_tracked() 如果垃圾收集器跟踪给定实例,则返回 true,否则返回 false。 (由 Antoine Pitrou 提供;:issue:`4688`。)
gzip 模块的 GzipFile 现在支持上下文管理协议,因此您可以编写
with gzip.GzipFile(...) as f:
(由 Hagen Fürstenau 提供;:issue:`3860` ]),现在它实现了 io.BufferedIOBase ABC,所以你可以用 io.BufferedReader 包装它以加快处理速度(由 Nir Aides 提供;:issue:` 7471`)。 现在还可以通过向构造函数提供可选的时间戳来覆盖 gzip 文件中记录的修改时间。 (由 Jacques Frechet 提供;:issue:`4272`。)gzip 格式的文件可以用尾随零字节填充; gzip 模块现在将消耗这些尾随字节。 (由 Tadek Pietraszek 和 Brian Curtin 修复;:问题:`2846`。)
新属性:hashlib 模块现在有一个
algorithms
属性,其中包含一个命名支持算法的元组。 在 Python 2.7 中,hashlib.algorithms
包含('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
。 (由 Carl Chenet 提供;:issue:`7418`。)httplib
模块使用的默认HTTPResponse
类现在支持缓冲,从而可以更快地读取 HTTP 响应。 (由 Kristján Valur Jónsson 提供;:issue:`4879`。)HTTPConnection
和HTTPSConnection
类现在支持 source_address 参数,(host, port)
2 元组给出将用于连接的源地址。 (由 Eldon Ziegler 提供;:issue:`3972`。)ihooks
模块现在支持相对导入。 请注意,ihooks
是用于自定义导入的旧模块,已被 Python 2.0 中添加的imputil
模块取代。 (Neil Schemenauer 添加的相对导入支持。)imaplib 模块现在支持 IPv6 地址。 (由 Derek Morr 提供;:issue:`1655`。)
新函数:inspect 模块的 getcallargs() 接受一个 callable 及其位置和关键字参数,并找出可调用的哪些参数将接收每个参数,返回一个字典映射参数名称到他们的价值观。 例如:
>>> from inspect import getcallargs >>> def f(a, b=1, *pos, **named): ... pass >>> getcallargs(f, 1, 2, 3) {'a': 1, 'b': 2, 'pos': (3,), 'named': {}} >>> getcallargs(f, a=2, x=4) {'a': 2, 'b': 1, 'pos': (), 'named': {'x': 4}} >>> getcallargs(f) Traceback (most recent call last): ... TypeError: f() takes at least 1 argument (0 given)
乔治·萨基斯供稿; :问题:`3135`。
更新模块:io 库已升级到 Python 3.1 附带的版本。 对于 3.1,I/O 库完全用 C 语言重写,速度提高了 2 到 20 倍,具体取决于正在执行的任务。 最初的 Python 版本被重命名为
_pyio
模块。一个小的结果变化:io.TextIOBase 类现在有一个
errors
属性,给出用于编码和解码错误的错误设置('strict'
、[ X178X]、'ignore'
)。io.FileIO 类现在在传递无效文件描述符时引发 OSError。 (由 Benjamin Peterson 实施;:issue:`4991`。)truncate() 方法现在保留文件位置; 以前它会将文件位置更改为新文件的末尾。 (由 Pascal Chambon 修正;:问题:`6939`。)
新函数:
itertools.compress(data, selectors)
需要两个迭代器。 如果 selectors 中的相应值为真,则返回 data 的元素:itertools.compress('ABCDEF', [1,0,1,0,1,1]) => A, C, E, F
新函数:
itertools.combinations_with_replacement(iter, r)
从可迭代的 iter 返回所有可能的 r 长度的元素组合。 与 combinations() 不同,单个元素可以在生成的组合中重复:itertools.combinations_with_replacement('abc', 2) => ('a', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'b'), ('b', 'c'), ('c', 'c')
请注意,元素被视为唯一取决于它们在输入中的位置,而不是它们的实际值。
itertools.count() 函数现在有一个 step 参数,允许按 1 以外的值递增。 count() 现在还允许关键字参数,并使用非整数值,例如浮点数或 Decimal 实例。 (由 Raymond Hettinger 实施;:issue:`5032`。)
itertools.combinations() 和 itertools.product() 之前为 r 大于输入迭代的值引发了 ValueError。 这被认为是规范错误,所以他们现在返回一个空的迭代器。 (由 Raymond Hettinger 修复;:问题:`4816`。)
更新模块: json 模块升级到 simplejson 包的 2.0.9 版本,其中包含一个 C 扩展,使编码和解码更快。 (由 Bob Ippolito 提供;:issue:`4136`。)
为了支持新的 collections.OrderedDict 类型,json.load() 现在有一个可选的 object_pairs_hook 参数,它将被任何解码为对列表。 (由 Raymond Hettinger 提供;:issue:`5381`。)
mailbox 模块的 Maildir 类现在在它读取的目录上记录时间戳,并且只有在修改时间随后发生变化时才会重新读取它们。 这通过避免不必要的目录扫描来提高性能。 (由 AM 修正 库克林和安托万·皮特鲁; :问题:`1607951`,:问题:`6896`。)
新函数:math 模块获得了 erf() 和 erfc() 用于误差函数和互补误差函数,expm1() ] 计算
e**x - 1
比使用 exp() 并减去 1、gamma() 用于 Gamma 函数和 lgamma() 的精度更高] 用于 Gamma 函数的自然对数。 (由 Mark Dickinson 和 nirinA raseliarison 提供;:issue:`3366`。)multiprocessing 模块的
Manager*
类现在可以传递一个可调用对象,该可调用对象将在子进程启动时调用,以及一组将传递给可调用对象的参数。 (由 lekma 提供;:issue:`5585`。)控制工作进程池的
Pool
类现在有一个可选的 maxtasksperchild 参数。 工作进程将执行指定数量的任务然后退出,导致Pool
启动一个新的工作进程。 如果任务可能会泄漏内存或其他资源,或者某些任务会导致工作线程变得非常大,这将非常有用。 (由 Charles Cazabon 提供;:问题:`6963`。)nntplib 模块现在支持 IPv6 地址。 (由 Derek Morr 提供;:issue:`1664`。)
新函数:os 模块封装了以下 POSIX 系统调用:getresgid() 和 getresuid(),它们返回真实的、有效的和保存的 GID 和UID; setresgid() 和 setresuid(),将真实、有效和保存的 GID 和 UID 设置为新值; initgroups(),初始化当前进程的组访问列表。 (由 Travis H. 贡献的 GID/UID 函数;:issue:`6508`。 支持由 Jean-Paul Calderone 添加的 initgroups; :问题:`7333`。)
os.fork() 函数现在重新初始化子进程中的导入锁; 当从线程调用 fork() 时,这解决了 Solaris 上的问题。 (由 Zsolt Cserna 修复;:问题:`7242`。)
在 os.path 模块中,normpath() 和 abspath() 函数现在保留了 Unicode; 如果它们的输入路径是一个 Unicode 字符串,则返回值也是一个 Unicode 字符串。 (normpath() 由 Matt Giuca 在 中修复:问题:`5827`;abspath() 由 Ezio Melotti 在 中修复:问题:`3426 `。)
pydoc 模块现在对 Python 使用的各种符号有帮助。 例如,您现在可以执行
help('<<')
或help('@')
。 (由 David Laban 提供;:issue:`4739`。)re 模块的 split()、sub() 和 subn() 现在接受一个可选的 flags参数,以便与模块中的其他函数保持一致。 (由格雷戈里 P. 史密斯。)
新函数:runpy 模块中的 run_path() 将在提供的 path 参数处执行代码。 path 可以是 Python 源文件(
example.py
)、编译后的字节码文件(example.pyc
)、目录(./package/
)或一个 zip 存档 (example.zip
)。 如果提供目录或zip路径,则将其添加到sys.path
的前面并导入模块__main__。 预计目录或 zip 包含__main__.py
; 如果没有,则可能会从稍后在sys.path
中的某个位置导入其他一些__main__.py
。 这使得 runpy 的更多机制可用于想要模仿 Python 命令行处理显式路径名方式的脚本。 (由 Nick Coghlan 添加;:issue:`6816`。)新函数:在 shutil 模块中,make_archive() 接受文件名、存档类型(zip 或 tar 格式)和目录路径,并创建包含目录内容的存档. (由 Tarek Ziadé 添加。)
shutil 的 copyfile() 和 copytree() 函数现在在被要求复制命名管道时引发
SpecialFileError
异常。 以前,代码会将命名管道视为普通文件,通过打开它们进行读取,这将无限期地阻塞。 (由 Antoine Pitrou 修复;:问题:`3002`。)signal 模块不再重新安装信号处理程序,除非确实有必要,这修复了一个可能导致无法稳健捕获 EINTR 信号的错误。 (由 Charles-Francois Natali 修复;:issue:`8354`。)
新函数:在 site 模块中,三个新函数返回各种特定于站点和用户的路径。 getsitepackages() 返回包含所有全局站点包目录的列表,getusersitepackages() 返回用户站点包目录的路径,getuserbase()返回
USER_BASE
环境变量的值,给出可用于存储数据的目录的路径。 (由 Tarek Ziadé 提供;:issue:`6693`。)site 模块现在报告导入
sitecustomize
模块时发生的异常,并且将不再捕获和吞下 KeyboardInterrupt 异常。 (由 Victor Stinner 修复;:问题:`3137`。)create_connection() 函数获得了一个 source_address 参数,一个
(host, port)
2 元组给出了将用于连接的源地址。 (由 Eldon Ziegler 提供;:issue:`3972`。)recv_into() 和 recvfrom_into() 方法现在将写入支持缓冲区 API 的对象,最有用的是 bytearray 和 memoryview对象。 (由 Antoine Pitrou 实施;:issue:`8104`。)
SocketServer
模块的TCPServer
类现在支持套接字超时并禁用 Nagle 算法。disable_nagle_algorithm
类属性默认为False
; 如果覆盖为 true,新的请求连接将设置 TCP_NODELAY 选项以防止将许多小发送缓冲到单个 TCP 数据包中。timeout
类属性可以保存将应用于请求套接字的以秒为单位的超时; 如果在该时间内没有收到请求,将调用handle_timeout()
并返回handle_request()
。 (由 Kristján Valur Jónsson 提供;:issue:`6192` 和 :issue:`6267`。)更新模块:sqlite3 模块已更新至 pysqlite 包 的 2.6.0 版。 版本 2.6.0 包括许多错误修正,并增加了从共享库加载 SQLite 扩展的能力。 调用
enable_load_extension(True)
方法启用扩展,然后调用 load_extension() 加载特定共享库。 (由 Gerhard Häring 更新。)ssl 模块的 SSLSocket 对象现在支持缓冲区 API,它修复了测试套件失败(由 Antoine Pitrou 修复;:issue:`7133`)并自动设置 OpenSSL 的
SSL_MODE_AUTO_RETRY
,这将防止从触发 SSL 重新协商的recv()
操作返回错误代码(由 Antoine Pitrou 修复;:issue:`8222`)。ssl.wrap_socket() 构造函数现在接受一个 ciphers 参数,它是一个列出允许使用的加密算法的字符串; 字符串的格式在 OpenSSL 文档 中描述 。 (由 Antoine Pitrou 添加;:issue:`8322`。)
另一个更改使扩展加载所有 OpenSSL 的密码和摘要算法,以便它们都可用。 某些 SSL 证书无法验证,报告“未知算法”错误。 (由 Beda Kosata 报道,由 Antoine Pitrou 修复;:问题:`8484`。)
正在使用的 OpenSSL 版本现在可用作模块属性 ssl.OPENSSL_VERSION(字符串)、ssl.OPENSSL_VERSION_INFO(5 元组)和 ssl.OPENNUMBERSION_VERSION (整数)。 (由 Antoine Pitrou 添加;:issue:`8321`。)
当值对于特定整数格式代码(
bBhHiIlLqQ
之一)太大时,struct 模块将不再默默忽略溢出错误; 它现在总是引发 struct.error 异常。 (由 Mark Dickinson 更改;:issue:`1523`。)pack() 函数也将尝试使用__index__()
转换和打包之前的非整数尝试__int__()
方法或报告错误。 (由 Mark Dickinson 更改;:issue:`8300`。)新函数:subprocess 模块的 check_output() 运行具有指定参数集的命令,并在命令运行无错误时以字符串形式返回命令的输出,或引发 [X214X ]CalledProcessError 否则异常。
>>> subprocess.check_output(['df', '-h', '.']) 'Filesystem Size Used Avail Capacity Mounted on\n /dev/disk0s2 52G 49G 3.0G 94% /\n' >>> subprocess.check_output(['df', '-h', '/bogus']) ... subprocess.CalledProcessError: Command '['df', '-h', '/bogus']' returned non-zero exit status 1
(由格雷戈里 P. 史密斯。)
subprocess 模块现在将在接收到
EINTR
信号时重试其内部系统调用。 (由几个人报道;最终补丁由 Gregory P. 中的史密斯:问题:`1068268`。)新函数:symtable 模块中的 is_declared_global() 对于显式声明为全局的变量返回 true,对于隐式全局变量返回 false。 (由杰里米·希尔顿提供。)
syslog 模块现在将使用
sys.argv[0]
的值作为标识符,而不是之前的默认值'python'
。 (由 Sean Reifschneider 更改;:issue:`8451`。)sys.version_info
值现在是一个命名元组,其属性名为major
、minor
、micro
、releaselevel
和 [ X116X]。 (由 Ross Light 提供;:issue:`4285`。)sys.getwindowsversion() 还返回一个命名元组,其属性名为
major
、minor
、build
、platform、[ X135X]、service_pack_major
、service_pack_minor
、suite_mask
和product_type
。 (由 Brian Curtin 提供;:问题:`7766`。)tarfile 模块的默认错误处理已更改,不再抑制致命错误。 默认错误级别以前为 0,这意味着错误只会导致将消息写入调试日志,但由于默认情况下未激活调试日志,因此不会注意到这些错误。 默认错误级别现在是 1,如果有错误,它会引发异常。 (由 Lars Gustäbel 更改;:issue:`7357`。)
tarfile 现在支持过滤添加到 tar 文件的 TarInfo 对象。 当您调用 add() 时,您可以提供一个可选的 filter 参数,该参数是可调用的。 filter callable 将为每个添加的文件传递 TarInfo,并且可以修改和返回它。 如果可调用函数返回
None
,则该文件将从生成的存档中排除。 这比现有的 exclude 参数更强大,因此已被弃用。 (由 Lars Gustäbel 添加;:issue:`6856`。)TarFile 类现在也支持上下文管理协议。 (由 Lars Gustäbel 添加;:issue:`7232`。)threading.Event 类的 wait() 方法现在在退出时返回内部标志。 这意味着该方法通常会返回 true,因为 wait() 应该阻塞,直到内部标志变为 true。 如果提供了超时并且操作超时,则返回值只会为 false。 (由 Tim Lesher 提供;:问题:`1674032`。)
unicodedata 模块提供的 Unicode 数据库现在在内部用于确定哪些字符是数字、空格或表示换行符。 该数据库还包括来自
Unihan.txt
数据文件(Anders Chrigström 和 Amaury Forgeot d'Arc 的补丁;:issue:`1571184`)的信息,并已更新至 5.2.0 版(由 Florent Xicluna 更新;:issue:`8024`)。urlparse
模块的urlsplit()
现在以符合 RFC 3986 的方式处理未知 URL 方案:如果 URL 的形式为 [ X151X],://
之前的文本被视为方案,即使它是模块不知道的编造方案。 此更改可能会破坏解决旧行为的代码。 例如,Python 2.6.4 或 2.5 将返回以下内容:>>> import urlparse >>> urlparse.urlsplit('invented://host/filename?query') ('invented', '', '//host/filename?query', '', '')
Python 2.7(和 Python 2.6.5)将返回:
>>> import urlparse >>> urlparse.urlsplit('invented://host/filename?query') ('invented', 'host', '/filename?query', '', '')
(Python 2.7 实际上产生稍微不同的输出,因为它返回一个命名元组而不是标准元组。)
urlparse
模块还支持 RFC 2732(由 Senthil Kumaran 提供;:issue:`2987`)定义的 IPv6 文字地址。>>> urlparse.urlparse('http://[1080::8:800:200C:417A]/foo') ParseResult(scheme='http', netloc='[1080::8:800:200C:417A]', path='/foo', params='', query='', fragment='')
新类:weakref 模块中的 WeakSet 类是一个只包含对其元素的弱引用的集合; 一旦没有指向它们的引用,元素将被删除。 (最初由 Raymond Hettinger 在 Python 3.x 中实现,并由 Michael Foord 向后移植到 2.7。)
ElementTree 库
xml.etree
在输出 XML 处理指令(看起来像<?xml-stylesheet href="#style1"?>
)或注释(看起来像<!-- comment -->
)时不再转义和号和尖括号。 (Neil Muller 的补丁;:问题:`2746`。)XML-RPC 客户端和服务器由
xmlrpclib
和SimpleXMLRPCServer
模块提供,通过支持 HTTP/1.1 保持活动和可选地使用 gzip 编码来压缩正在交换的 XML,从而提高了性能。 gzip 压缩由SimpleXMLRPCRequestHandler
的encode_threshold
属性控制,该属性包含一个字节大小; 大于此值的响应将被压缩。 (由 Kristján Valur Jónsson 提供;:issue:`6267`。)zipfile 模块的 ZipFile 现在支持上下文管理协议,因此您可以编写
with zipfile.ZipFile(...) as f:
。 (由 Brian Curtin 提供;:issue:`5511`。)zipfile 现在还支持归档空目录并正确提取它们。 (由 Kuba Wieczorek 修复;:issue:`4710`。)从存档中读取文件更快,交错 read() 和
readline()
现在可以正常工作. (由 Nir Aides 提供;:问题:`7610`。)除了早期版本中接受的路径名之外,is_zipfile() 函数现在接受一个文件对象。 (由 Gabriel Genellina 提供;:issue:`4756`。)
writestr() 方法现在有一个可选的 compress_type 参数,可让您覆盖 ZipFile 构造函数中指定的默认压缩方法。 (由 Ronald Oussoren 提供;:issue:`6003`。)
新模块:importlib
Python 3.1 包含 importlib 包,这是对 Python 的 import 语句底层逻辑的重新实现。 importlib 对于 Python 解释器的实现者和希望编写可以参与导入过程的新导入器的用户非常有用。 Python 2.7 不包含完整的 importlib 包,而是包含一个包含单个函数 import_module() 的小子集。
import_module(name, package=None)
导入一个模块。 name 是包含模块或包名称的字符串。 可以通过提供以 .
字符开头的字符串来进行相对导入,例如 ..utils.errors
。 对于相对导入,必须提供 package 参数,它是将用作相对导入锚点的包的名称。 import_module() 都将导入的模块插入到 sys.modules
并返回模块对象。
这里有些例子:
>>> from importlib import import_module
>>> anydbm = import_module('anydbm') # Standard absolute import
>>> anydbm
<module 'anydbm' from '/p/python/Lib/anydbm.py'>
>>> # Relative import
>>> file_util = import_module('..file_util', 'distutils.command')
>>> file_util
<module 'distutils.file_util' from '/python/Lib/distutils/file_util.pyc'>
importlib 由 Brett Cannon 实现并在 Python 3.1 中引入。
新模块:sysconfig
sysconfig 模块已经从 Distutils 包中拉出来,成为一个新的顶级模块。 sysconfig 提供了获取有关 Python 构建过程信息的函数:编译器开关、安装路径、平台名称以及 Python 是否从其源目录运行。
模块中的一些功能是:
- get_config_var() 从 Python 的 Makefile 和
pyconfig.h
文件中返回变量。 - get_config_vars() 返回一个包含所有配置变量的字典。
- get_path() 返回特定类型模块的配置路径:标准库、站点特定模块、平台特定模块等。
- is_python_build() 如果您从 Python 源代码树运行二进制文件,则返回 true,否则返回 false。
请参阅 sysconfig 文档以获取更多详细信息和完整的功能列表。
Distutils 包和 sysconfig 现在由 Tarek Ziadé 维护,他还启动了一个用于开发的 Distutils2 包(源代码库位于 https://hg.python.org/distutils2/)下一代版本的 Distutils。
ttk:Tk 的主题小部件
Tcl/Tk 8.5 包括一组主题小部件,这些小部件重新实现了基本的 Tk 小部件,但具有更可定制的外观,因此可以更接近于本机平台的小部件。 这个小部件集最初被称为 Tile,但在添加到 Tcl/Tck 8.5 版后被重命名为 Ttk(用于“主题 Tk”)。
要了解更多信息,请阅读 ttk
模块文档。 您可能还希望阅读描述 Ttk 主题引擎的 Tcl/Tk 手册页,可从 https://www.tcl.tk/man/tcl8.5/TkCmd/ttk_intro.htm 获得。 正在使用的 Python/Ttk 代码的一些屏幕截图位于 https://code.google.com/archive/p/python-ttk/wikis/Screenshots.wiki。
ttk
模块由 Guilherme Polo 编写并添加到 :issue:`2983`。 由 Martin Franklin 编写并由 Kevin Walzer 维护的名为 Tile.py
的替代版本被提议包含在 :issue:`2618` 中,但作者认为 Guilherme Polo 的工作更全面.
更新模块:单元测试
unittest模块大大增强; 添加了许多新功能。 除非另有说明,否则大多数功能都是由 Michael Foord 实现的。 该模块的增强版本可单独下载,用于 Python 版本 2.4 到 2.6,打包为 unittest2
包,来自 https://pypi.org/project/unittest2。
从命令行使用时,该模块可以自动发现测试。 它不像 py.test 或 nose 那样花哨,但提供了一种简单的方法来运行保存在一组包目录中的测试。 例如,以下命令将在 test/
子目录中搜索名为 test*.py
的任何可导入测试文件:
python -m unittest discover -s test
有关更多详细信息,请参阅 unittest 模块文档。 (在 中开发:问题:`6001`。)
main() 函数支持其他一些新选项:
-b 或
--buffer
将在每次测试期间缓冲标准输出和标准错误流。 如果测试通过,任何结果输出将被丢弃; 失败时,将显示缓冲输出。-c 或
--catch
会导致 control-C 中断被更优雅地处理。 不会立即中断测试过程,而是会完成当前运行的测试,然后报告中断前的部分结果。 如果您不耐烦,第二次按下 control-C 将导致立即中断。当被测试的代码或正在运行的测试定义了自己的信号处理程序时,这个 control-C 处理程序试图避免引起问题,方法是注意到信号处理程序已经设置并调用它。 如果这对您不起作用,有一个 removeHandler() 装饰器可用于标记应该禁用 control-C 处理的测试。
-f 或
--failfast
使测试执行在测试失败时立即停止,而不是继续执行进一步的测试。 (由 Cliff Dyer 提出并由 Michael Foord 实施;:issue:`8074`。)
在详细模式下运行时,进度消息现在显示“x”表示预期失败,“u”表示意外成功。 (本杰明·彼得森供稿。)
测试用例可以引发 SkipTest 异常以跳过测试 (:issue:`1034053`)。
assertEqual()、assertTrue() 和 assertFalse() 故障的错误消息现在提供了更多信息。 如果您将 TestCase 类的 longMessage 属性设置为 true,则标准错误消息和您提供的任何其他消息都将打印失败。 (由 Michael Foord 添加;:issue:`5663`。)
assertRaises() 方法现在在调用时返回一个上下文处理程序,而无需提供可调用的对象来运行。 例如,你可以这样写:
with self.assertRaises(KeyError):
{}['foo']
(由 Antoine Pitrou 实施;:issue:`4444`。)
现在支持模块和类级别的设置和拆卸装置。 模块可以包含 setUpModule()
和 tearDownModule()
功能。 类可以有 setUpClass() 和 tearDownClass() 方法,它们必须定义为类方法(使用 @classmethod
或等效方法)。 当测试运行程序切换到不同模块或类中的测试用例时,将调用这些函数和方法。
添加了方法 addCleanup() 和 doCleanups()。 addCleanup() 允许您添加将无条件调用的清理函数(在 setUp() 之后,如果 setUp() 失败,否则在 tearDown() 之后)。 这允许在测试期间更简单的资源分配和释放 (:issue:`5679`)。
添加了许多新方法以提供更专业的测试。 其中许多方法是由 Google 工程师编写的,用于他们的测试套件; 格雷戈里·P。 Smith、Michael Foord 和 GvR 致力于将它们合并到 Python 的 unittest 版本中。
- assertIsNone() 和 assertIsNotNone() 取一个表达式并验证结果是否为
None
。 - assertIs() 和 assertIsNot() 取两个值并检查这两个值是否计算为同一个对象。 (由 Michael Foord 添加;:issue:`2578`。)
- assertIsInstance() 和 assertNotIsInstance() 检查结果对象是特定类的实例,还是类元组之一的实例。 (由 Georg Brandl 添加;:issue:`7031`。)
- assertGreater()、assertGreaterEqual()、assertLess()和assertLessEqual()比较两个数量。
- assertMultiLineEqual() 比较两个字符串,如果它们不相等,则显示一个有用的比较,突出显示两个字符串中的差异。 当 Unicode 字符串与 assertEqual() 进行比较时,现在默认使用此比较。
assertRegexpMatches()
和assertNotRegexpMatches()
检查第一个参数是否与作为第二个参数提供的正则表达式匹配或不匹配 (:issue:`8038`)。assertRaisesRegexp()
检查是否引发了特定异常,然后还检查异常的字符串表示是否与提供的正则表达式匹配。- assertIn() 和 assertNotIn() 测试 first 是否在 second 中。
assertItemsEqual()
测试两个提供的序列是否包含相同的元素。- assertSetEqual()比较两个集合是否相等,出错时只报告集合之间的差异。
- 类似地, assertListEqual() 和 assertTupleEqual() 比较指定的类型并解释任何差异,而不必打印它们的完整值; 在使用 assertEqual() 比较列表和元组时,现在默认使用这些方法。 更一般地, assertSequenceEqual() 比较两个序列,并且可以选择检查两个序列是否属于特定类型。
- assertDictEqual() 比较两个字典并报告差异; 当您使用 assertEqual() 比较两个字典时,它现在默认使用。
assertDictContainsSubset()
检查是否在 second 中找到 first 中的所有键/值对。 - assertAlmostEqual() 和 assertNotAlmostEqual() 测试 first 和 second 是否近似相等。 此方法可以将它们的差值舍入到可选指定数量的 位置 (默认值为 7)并将其与零进行比较,或者要求差值小于提供的 delta价值。
- loadTestsFromName() 正确遵守 TestLoader 的 suiteClass 属性。 (由 Mark Roddy 修复;:问题:`6866`。)
- 一个新的钩子可以让你扩展 assertEqual() 方法来处理新的数据类型。 addTypeEqualityFunc() 方法接受一个类型对象和一个函数。 当被比较的两个对象都属于指定类型时,将使用该函数。 这个函数应该比较两个对象,如果它们不匹配就抛出一个异常; 该函数提供有关为什么两个对象不匹配的附加信息是一个好主意,就像新的序列比较方法一样。
unittest.main() 现在采用可选的 exit
参数。 如果为 false,则 main() 不会调用 sys.exit(),从而允许从交互式解释器中使用 main()。 (由 J. 巴勃罗·费尔南德斯; :问题:`3379`。)
TestResult 具有新的 startTestRun() 和 stopTestRun() 方法,它们在测试运行前后立即调用。 (由罗伯特柯林斯提供;:问题:`5728`。)
随着所有这些变化,unittest.py
变得笨拙地大,所以模块变成了一个包,代码分成几个文件(由 Benjamin Peterson)。 这不会影响模块的导入或使用方式。
也可以看看
- http://www.voidspace.org.uk/python/articles/unittest2.shtml
- 描述新功能、如何使用它们以及各种设计决策的基本原理。 (迈克尔·福特着。)
更新模块:ElementTree 1.3
Python 中包含的 ElementTree 库版本已更新至 1.3 版。 一些新功能是:
各种解析函数现在采用 parser 关键字参数,给出将使用的 XMLParser 实例。 这使得可以覆盖文件的内部编码:
p = ET.XMLParser(encoding='utf-8') t = ET.XML("""<root/>""", parser=p)
解析 XML 中的错误现在会引发
ParseError
异常,其实例具有position
属性,其中包含一个 (line, column) 元组,给出位置问题。ElementTree 用于将树转换为字符串的代码已进行了重大修改,使其在许多情况下的速度大约是其两倍。 ElementTree.write() 和
Element.write()
方法现在有一个 method 参数,可以是“xml”(默认)、“html”或“text” . HTML 模式将空元素输出为<empty></empty>
而不是<empty/>
,文本模式将跳过元素并只输出文本块。 如果将元素的tag
属性设置为None
但将其子元素保留在原位,则在写出树时该元素将被省略,因此您不需要做更多的扩展重新排列以删除单个元素。命名空间处理也得到了改进。 所有
xmlns:<whatever>
声明现在都在根元素上输出,而不是分散在生成的 XML 中。 您可以通过设置default_namespace
属性来设置树的默认命名空间,并且可以使用 register_namespace() 注册新前缀。 在 XML 模式下,您可以使用 true/false xml_declaration 参数来取消 XML 声明。新的 Element 方法:extend() 将序列中的项目附加到元素的子元素。 元素本身的行为类似于序列,因此很容易将子元素从一个元素移动到另一个元素:
from xml.etree import ElementTree as ET t = ET.XML("""<list> <item>1</item> <item>2</item> <item>3</item> </list>""") new = ET.XML('<root/>') new.extend(t) # Outputs <root><item>1</item>...</root> print ET.tostring(new)
新的
Element
方法:iter() 生成元素的子元素作为生成器。 也可以编写for child in elem:
来循环元素的子元素。 现有方法getiterator()
现在已弃用,getchildren()
构造并返回子项列表也是如此。新的
Element
方法:itertext() 产生作为元素后代的所有文本块。 例如:t = ET.XML("""<list> <item>1</item> <item>2</item> <item>3</item> </list>""") # Outputs ['\n ', '1', ' ', '2', ' ', '3', '\n'] print list(t.itertext())
不推荐使用:将元素用作布尔值(即
if elem:
),如果该元素有任何子元素,则返回 true,如果没有子元素,则返回 false。 这种行为令人困惑——None
是假的,但无子元素也是假的? – 所以它现在会触发 FutureWarning。 在你的代码中,你应该明确:如果你对孩子的数量感兴趣,写len(elem) != 0
,或者写elem is not None
。
Fredrik Lundh 开发了 ElementTree 并制作了 1.3 版本; 您可以在 http://effbot.org/zone/elementtree-13-intro.htm 阅读他描述 1.3 的文章。 Florent Xicluna 在讨论 python-dev 和 :issue:`6472` 后更新了 Python 包含的版本。)
构建和 C API 更改
Python 构建过程和 C API 的更改包括:
最新版本的 GNU 调试器 GDB 7 可以使用 Python 编写 脚本。 当你开始调试一个可执行程序 P 时,GDB 会寻找一个名为
P-gdb.py
的文件并自动读取它。 Dave Malcolm 贡献了一个python-gdb.py
,它添加了许多在调试 Python 本身时有用的命令。 例如,py-up
和py-down
上升或下降一个 Python 堆栈帧,通常对应几个 C 堆栈帧。py-print
打印 Python 变量的值,py-bt
打印 Python 堆栈跟踪。 (作为 :issue:`8032` 的结果添加。)如果你使用 Python 提供的
.gdbinit
文件,当被调试的线程不持有 GIL 时,2.7 版本中的“pyo”宏现在可以正常工作; 宏现在在打印之前获取它。 (由 Victor Stinner 提供;:问题:`3632`。)Py_AddPendingCall() 现在是线程安全的,允许任何工作线程向主 Python 线程提交通知。 这对于异步 IO 操作特别有用。 (由 Kristján Valur Jónsson 提供;:issue:`4293`。)
新函数:PyCode_NewEmpty() 创建一个空代码对象; 只需要文件名、函数名和第一行号。 这对于尝试构建更有用的回溯堆栈的扩展模块很有用。 以前这样的扩展需要调用 PyCode_New(),它有更多的参数。 (由杰弗里亚斯金添加。)
新函数:PyErr_NewExceptionWithDoc() 创建一个新的异常类,就像现有的 PyErr_NewException() 一样,但需要一个额外的
char *
参数,其中包含新的文档字符串异常类。 (由 Python 错误跟踪器上的“lekma”添加;:issue:`7033`。)新函数:PyFrame_GetLineNumber() 接受一个框架对象并返回框架当前正在执行的行号。 以前的代码需要获取当前正在执行的字节码指令的索引,然后查找与该地址对应的行号。 (由杰弗里亚斯金添加。)
新函数:PyLong_AsLongAndOverflow() 和 PyLong_AsLongLongAndOverflow() 将 Python 长整数近似为 C long 或 long long。 如果数字太大而不适合输出类型,则设置 overflow 标志并将其返回给调用者。 (由 Case Van Horsen 提供;:issue:`7528` 和 :issue:`7767`。)
新函数:由于重写了字符串到浮点数的转换,增加了一个新的 PyOS_string_to_double() 函数。 旧的
PyOS_ascii_strtod()
和PyOS_ascii_atof()
函数现已弃用。新函数:PySys_SetArgvEx() 设置
sys.argv
的值,并且可以选择更新sys.path
以包含包含由sys.argv[0]
命名的脚本的目录,具体取决于updatepath 参数的值。添加此功能是为了关闭嵌入 Python 的应用程序的安全漏洞。 旧函数 PySys_SetArgv() 将始终更新
sys.path
,有时它会添加当前目录。 这意味着,如果您在其他人控制的目录中运行嵌入 Python 的应用程序,攻击者可以将特洛伊木马模块放入您的应用程序随后将导入的目录(例如,名为os.py
的文件)中跑。如果您维护一个嵌入 Python 的 C/C++ 应用程序,请检查您是否正在调用 PySys_SetArgv() 并仔细考虑该应用程序是否应该使用 PySys_SetArgvEx() 和 updatepath 设置为假。
安全问题报告为 CVE-2008-5983; 在 :issue:`5753` 中讨论,并由 Antoine Pitrou 修复。
新宏:Python 头文件现在定义了以下宏:
Py_ISALNUM
、Py_ISALPHA
、Py_ISDIGIT
、Py_ISLOWER
、Py_ISSPACE
、Py_ISUPPER
、Py_ISXDIGIT
、Py_TOLOWER
和Py_TOUPPER
。 所有这些函数都类似于用于分类字符的 C 标准宏,但忽略当前的语言环境设置,因为在一些地方 Python 需要以独立于语言环境的方式分析字符。 (由 Eric Smith 添加;:issue:`5793`。)移除的功能:
PyEval_CallObject
现在只能作为宏使用。 保留了一个函数版本以保持 ABI 链接兼容性,但那是在 1997 年; 现在当然可以删除它。 (由 Antoine Pitrou 删除;:issue:`8276`。)新格式代码:
PyFormat_FromString()
、PyFormat_FromStringV()
和 PyErr_Format() 函数现在接受%lld
和%llu
格式代码来显示 C 长长型。 (由 Mark Dickinson 提供;:issue:`7228`。)线程和进程分叉之间的复杂交互已经改变。 以前,由 os.fork() 创建的子进程可能会失败,因为子进程创建时只有一个线程在运行,该线程执行 os.fork()。 如果其他线程持有锁,例如 Python 的导入锁,则在执行 fork 时,该锁仍会在新进程中被标记为“持有”。 但是在子进程中没有任何东西会释放锁,因为其他线程没有被复制,并且子进程将不再能够执行导入。
Python 2.7 在执行 os.fork() 之前获取导入锁,并且还会清除使用 threading 模块创建的任何锁。 具有内部锁或调用
fork()
自身的 C 扩展模块不会从这种清理中受益。(由 Thomas Wouters 修复;:问题:`1590864`。)
Py_Finalize() 函数现在调用内部的
threading._shutdown()
函数; 这可以防止在解释器关闭时引发一些异常。 (亚当奥尔森的补丁;:问题:`1722344`。)当使用 PyMemberDef 结构体定义类型的属性时,Python 将不再允许您尝试删除或设置
T_STRING_INPLACE
属性。ctypes 模块定义的全局符号现在以
Py
或_ctypes
为前缀。 (由 Thomas Heller 实施;:issue:`3102`。)新的配置选项:
--with-system-expat
开关允许构建pyexpat
模块以使用系统 Expat 库。 (由 Arfrever Frehtes Taifersar Arahesis 提供;:issue:`7609`。)新的配置选项:
--with-valgrind
选项现在将禁用 pymalloc 分配器,这对于 Valgrind 内存错误检测器来说很难正确分析。 因此,Valgrind 将更好地检测内存泄漏和溢出。 (由 James Henstridge 提供;:issue:`2422`。)新的配置选项:您现在可以向
--with-dbmliborder=
提供一个空字符串,以禁用所有各种 DBM 模块。 (由 Arfrever Frehtes Taifersar Arahesis 添加;:issue:`6491`。)configure 脚本现在检查某些 32 位 Intel 芯片上的浮点舍入错误,并定义
X87_DOUBLE_ROUNDING
预处理器定义。 当前没有代码使用此定义,但如果有人希望使用它,则可以使用它。 (由 Mark Dickinson 添加;:issue:`2937`。)configure 现在还设置了一个
LDCXXSHARED
Makefile 变量以支持 C++ 链接。 (由 Arfrever Frehtes Taifersar Arahesis 提供;:issue:`1222585`。)构建过程现在为 pkg-config 支持创建必要的文件。 (由克林顿罗伊提供;:问题:`3585`。)
构建过程现在支持 Subversion 1.7。 (由 Arfrever Frehtes Taifersar Arahesis 提供;:issue:`6094`。)
胶囊
Python 3.1 添加了新的 C 数据类型 PyCapsule,用于为扩展模块提供 C API。 胶囊本质上是 C void *
指针的持有者,并作为模块属性提供; 例如,socket 模块的 API 公开为 socket.CAPI
,而 unicodedata 公开 ucnhash_CAPI
。 其他扩展可以导入模块,访问其字典获取胶囊对象,然后获取 void *
指针,该指针通常会指向指向模块各种 API 函数的指针数组。
已经为此使用了一个现有的数据类型,PyCObject
,但它不提供类型安全。 通过从模块 A 中获取 PyCObject
并以某种方式将其替换为模块 B 中的 PyCObject
,用纯 Python 编写的恶意代码可能会导致分段错误。 Capsule 知道自己的名字,获取指针需要提供名字:
void *vtable;
if (!PyCapsule_IsValid(capsule, "mymodule.CAPI") {
PyErr_SetString(PyExc_ValueError, "argument type invalid");
return NULL;
}
vtable = PyCapsule_GetPointer(capsule, "mymodule.CAPI");
您确信 vtable
指向您所期望的任何内容。 如果传入了不同的胶囊,PyCapsule_IsValid() 将检测到不匹配的名称并返回 false。 有关使用这些对象的更多信息,请参阅 为扩展模块提供 C API 。
Python 2.7 现在在内部使用胶囊来提供各种扩展模块 API,但 PyCObject_AsVoidPtr()
被修改为处理胶囊,保留与 CObject
接口的编译时兼容性。 使用 PyCObject_AsVoidPtr()
将发出 PendingDeprecationWarning 信号,默认情况下是静默的。
在 Python 3.1 中实现并由 Larry Hastings 向后移植到 2.7; 在 :issue:`5630` 中讨论。
特定于端口的更改:Windows
- msvcrt 模块现在包含来自
crtassem.h
头文件的一些常量:CRT_ASSEMBLY_VERSION
、VC_ASSEMBLY_PUBLICKEYTOKEN
和LIBRARIES_ASSEMBLY_NAME_PREFIX
。 (由 David Cournapeau 提供;:issue:`4365`。) - 用于访问注册表的
_winreg
模块现在实现了CreateKeyEx()
和DeleteKeyEx()
函数,这些函数是以前支持的函数的扩展版本,带有几个额外的参数。DisableReflectionKey()
、EnableReflectionKey()
和QueryReflectionKey()
也经过测试和记录。 (由 Brian Curtin 实施::问题:`7347`。) - 新的
_beginthreadex()
API 用于启动线程,现在使用原生线程本地存储功能。 (由 Kristján Valur Jónsson 提供;:issue:`3582`。) - os.kill() 函数现在适用于 Windows。 信号值可以是常数
CTRL_C_EVENT
、CTRL_BREAK_EVENT
或任何整数。 前两个常量会将 Control-C 和 Control-Break 按键事件发送到子进程; 任何其他值都将使用TerminateProcess()
API。 (由 Miki Tebeka 提供;:issue:`1220212`。) - os.listdir() 函数现在对于空路径正确失败。 (由 Hirokazu Yamamoto 修复;:问题:`5913`。)
mimelib
模块现在将在初始化时从 Windows 注册表读取 MIME 数据库。 (Gabriel Genellina 的补丁;:问题:`4969`。)
特定于端口的更改:Mac OS X
路径
/Library/Python/2.7/site-packages
现在附加到sys.path
,以便在系统安装和用户安装的相同版本副本之间共享添加的包。 (由 Ronald Oussoren 更改;:issue:`4865`。)2.7.13 版更改: 自 2.7.13 起,此更改已删除。
/Library/Python/2.7/site-packages
,Apple 提供的系统 Python 2.7 使用的 site-packages 目录不再附加到sys.path
,用于用户安装的 Python,例如来自 python.org 安装程序。 从 macOS 10.12 开始,Apple 更改了系统 site-packages 目录的配置方式,这可能导致安装 pip 组件(如 setuptools)失败。 为系统 Python 安装的包将不再与用户安装的 Python 共享。 (:问题:`28440`)
特定于端口的更改:FreeBSD
- FreeBSD 7.1 的
SO_SETFIB
常量,与getsockopt()
/setsockopt()
一起使用来选择备用路由表,现在在 socket 模块中可用。 (由 Kyle VanderBeek 添加;:issue:`8235`。)
其他更改和修复
- 两个基准脚本,
iobench
和ccbench
,被添加到Tools
目录中。iobench
测量 open() 返回的内置文件 I/O 对象在执行各种操作时的速度,而ccbench
是一个试图测量的并发基准使用不同数量的线程执行多个任务时的计算吞吐量、线程切换延迟和 IO 处理带宽。 Tools/i18n/msgfmt.py
脚本现在可以理解.po
文件中的复数形式。 (由 Martin von Löwis 修正;:issue:`5464`。)- 当从
.pyc
或.pyo
文件中导入模块时,该文件具有现有的.py
对应项,结果代码对象的co_filename
属性在原始文件名时被覆盖已过时。 如果文件已被重命名、移动或通过不同路径访问,就会发生这种情况。 (Ziga Seilnacht 和 Jean-Paul Calderone 的补丁;:问题:`1180193`。) regrtest.py
脚本现在采用--randseed=
开关,该开关采用一个整数作为-r
选项的随机种子,以随机顺序执行测试。-r
选项还报告使用的种子(由 Collin Winter 添加。)- 另一个
regrtest.py
开关是-j
,它采用一个整数指定并行运行的测试数量。 这允许减少多核机器上的总运行时间。 此选项与其他几个选项兼容,包括已知会产生较长运行时间的-R
开关。 (由 Antoine Pitrou 添加,:issue:`6152`。)这也可以与新的-F
开关一起使用,该开关循环运行选定的测试,直到它们失败。 (由 Antoine Pitrou 添加;:issue:`7312`。) - 当作为脚本执行时,
py_compile.py
模块现在接受'-'
作为参数,它将读取要编译的文件名列表的标准输入。 (由 Piotr Ożarowski 提供;:issue:`8233`。)
移植到 Python 2.7
本节列出了之前描述的更改和其他可能需要更改代码的错误修复:
- range() 函数更一致地处理其参数; 它现在将在提供给它的非浮点数、非整数参数上调用
__int__()
。 (由 Alexander Belopolsky 修正;:issue:`1533`。) - 字符串 format() 方法将用于浮点数和复数的默认精度从 6 位小数更改为 12 位,这与 str() 使用的精度相匹配。 (由 Eric Smith 更改;:issue:`5920`。)
- 由于对 with 语句的优化,特殊方法
__enter__()
和__exit__()
必须属于对象的类型,不能直接附加到对象的实例。 这会影响新式类(派生自 object)和 C 扩展类型。 (:问题:`6101`。) - 由于 Python 2.6 中的错误,
__exit__()
方法的 exc_value 参数通常是异常的字符串表示形式,而不是实例。 这在 2.7 中已修复,因此 exc_value 将是预期的实例。 (由 Florent Xicluna 修复;:问题:`7853`。) - 当使用
__slots__
设置一组受限制的属性时,删除未设置的属性不会像您预期的那样引发 AttributeError。 由本杰明·彼得森修复; :问题:`7604`。)
在标准库中:
使用 datetime 实例导致年份超出支持范围的操作并不总是引发 OverflowError。 现在会更仔细地检查此类错误,并将引发异常。 (Mark Leander 报道,Anand B. 皮莱和亚历山大·贝洛波尔斯基; :问题:`7150`。)
当将 Decimal 实例与字符串的 format() 方法一起使用时,默认对齐方式以前是左对齐方式。 这已更改为右对齐,这可能会更改程序的输出。 (由 Mark Dickinson 更改;:issue:`6857`。)
涉及信号 NaN 值(或
sNAN
)的比较现在发出信号 InvalidOperation,而不是根据比较运算符静默返回 true 或 false 值。 Quiet NaN 值(或NaN
)现在是可散列的。 (由 Mark Dickinson 修复;:问题:`7279`。)ElementTree 库,
xml.etree
, 在输出 XML 处理指令(看起来像 ) 或评论(看起来像 )。 (Neil Muller 的补丁;:问题:`2746`。)StringIO
对象的readline()
方法现在在请求负长度时不执行任何操作,就像其他类似文件的对象一样。 (:问题:`7348`)。syslog 模块现在将使用
sys.argv[0]
的值作为标识符,而不是之前的默认值'python'
。 (由 Sean Reifschneider 更改;:issue:`8451`。)tarfile 模块的默认错误处理已更改,不再抑制致命错误。 默认错误级别以前为 0,这意味着错误只会导致将消息写入调试日志,但由于默认情况下未激活调试日志,因此不会注意到这些错误。 默认错误级别现在是 1,如果有错误,它会引发异常。 (由 Lars Gustäbel 更改;:issue:`7357`。)
urlparse
模块的urlsplit()
现在以符合 RFC 3986 的方式处理未知 URL 方案:如果 URL 的形式为 [ X151X],://
之前的文本被视为方案,即使它是模块不知道的编造方案。 此更改可能会破坏解决旧行为的代码。 例如,Python 2.6.4 或 2.5 将返回以下内容:>>> import urlparse >>> urlparse.urlsplit('invented://host/filename?query') ('invented', '', '//host/filename?query', '', '')
Python 2.7(和 Python 2.6.5)将返回:
>>> import urlparse >>> urlparse.urlsplit('invented://host/filename?query') ('invented', 'host', '/filename?query', '', '')
(Python 2.7 实际上产生稍微不同的输出,因为它返回一个命名元组而不是标准元组。)
对于 C 扩展:
- 使用整数格式代码和
PyArg_Parse*
系列函数的 C 扩展现在将引发 TypeError 异常而不是触发 DeprecationWarning (:issue:`5080 `)。 - 使用新的 PyOS_string_to_double() 函数代替旧的
PyOS_ascii_strtod()
和PyOS_ascii_atof()
函数,这些函数现在已弃用。
对于嵌入 Python 的应用程序:
- 添加了 PySys_SetArgvEx() 函数,让应用程序在使用现有的 PySys_SetArgv() 函数时关闭安全漏洞。 检查您是否正在调用 PySys_SetArgv() 并仔细考虑应用程序是否应该使用 PySys_SetArgvEx() 并将 updatepath 设置为 false。
添加到 Python 2.7 维护版本的新功能
当情况真正需要时,新功能可能会添加到 Python 2.7 维护版本中。 任何此类添加都必须通过 Python 增强提案流程,并通过将新功能单独添加到 Python 3 或将其发布在 Python 包索引上来说明为什么无法充分解决这些问题。
除了下面列出的具体建议之外,还有一项一般豁免允许在任何 Python 2.7 维护版本中添加新的 -3
警告。
调试模式的两个新环境变量
在调试模式下,默认不写入 [xxx refs]
统计信息,现在还必须设置 PYTHONSHOWREFCOUNT
环境变量。 (由 Victor Stinner 提供;:问题:`31733`。)
当 Python 在定义 COUNT_ALLOC
的情况下编译时,默认情况下不再转储分配计数:现在还必须设置 PYTHONSHOWALLOCCOUNT
环境变量。 此外,分配计数现在转储到 stderr,而不是 stdout。 (由 Victor Stinner 提供;:问题:`31692`。)
2.7.15 版中的新功能。
PEP 434:所有分支的 IDLE 增强异常
PEP 434 描述了对随 Python 提供的 IDLE 开发环境所做更改的一般豁免。 此豁免使 IDLE 开发人员可以在所有受支持的 Python 2 和 3 版本中提供更一致的用户体验。
有关任何 IDLE 更改的详细信息,请参阅特定版本的 NEWS 文件。
PEP 466:Python 2.7 的网络安全增强
PEP 466 描述了许多网络安全增强提案,这些提案已被批准包含在 Python 2.7 维护版本中,其中第一个更改出现在 Python 2.7.7 版本中。
PEP 466 Python 2.7.7 相关特性:
- hmac.compare_digest() 从 Python 3 向后移植,使 Python 2 应用程序可以使用抗时序攻击的比较操作。 (由 Alex Gaynor 提供;:issue:`21306`。)
- OpenSSL 1.0.1g 在 python.org 上发布的官方 Windows 安装程序中进行了升级。 (由 Zachary Ware 提供;:issue:`21462`。)
PEP 466 Python 2.7.8 相关特性:
- hashlib.pbkdf2_hmac() 从 Python 3 向后移植,使散列算法适用于 Python 2 应用程序广泛使用的安全密码存储。 (由 Alex Gaynor 提供;:issue:`21304`。)
- OpenSSL 1.0.1h 已针对 python.org 上发布的官方 Windows 安装程序进行了升级。 (由 Zachary Ware 在 中贡献:issue:`21671` for CVE-2014-0224)
PEP 466 Python 2.7.9 相关特性:
Python 3.4 的大部分 ssl 模块都向后移植。 这意味着 ssl 现在支持服务器名称指示、TLS1.x 设置、访问平台证书存储、SSLContext 类和其他功能。 (由 Alex Gaynor 和 David Reid 提供;:issue:`21308`。)
具体细节请参考模块文档中的“版本添加:2.7.9”说明。
os.urandom() 已更改为将文件描述符缓存到
/dev/urandom
,而不是在每次调用时重新打开/dev/urandom
。 (由 Alex Gaynor 提供;:issue:`21305`。)hashlib.algorithms_guaranteed 和 hashlib.algorithms_available 从 Python 3 向后移植,使 Python 2 应用程序更容易选择最强的可用哈希算法。 (由 Alex Gaynor 在 中提供:issue:`21307`)
PEP 477:将确保pip(PEP 453)向后移植到 Python 2.7
PEP 477 批准包含 PEP 453 ensurepip 模块和在 Python 2.7 维护版本中启用的改进文档,首先出现在 Python 2.7.9 版本中。
默认引导 pip
新的 ensurepip 模块(在 PEP 453 中定义)提供了一个标准的跨平台机制来引导 pip 安装程序进入 Python 安装。 Python 2.7.9 附带的 pip
版本为 pip
1.5.6,未来的 2.7.x 维护版本会将捆绑版本更新为最新版本的 pip
在创建候选版本时可用。
默认情况下,命令 pip
、pipX
和 pipX.Y
将安装在所有平台上(其中 XY 代表 Python 安装的版本),以及 pip
Python 包及其依赖项。
对于在 POSIX 系统 上构建的 CPython 源代码,make install
和 make altinstall
命令默认不引导 pip
。 这种行为可以通过配置选项控制,并通过 Makefile 选项覆盖。
在 Windows 和 Mac OS X 上,CPython 安装程序现在默认安装 pip
以及 CPython 本身(用户可以在安装过程中选择不安装它)。 Window 用户需要选择自动 PATH
修改,默认情况下可以从命令行使用 pip
,否则仍然可以通过 Windows 的 Python 启动器以 [ X218X]。
正如 PEP 中讨论的 ,平台打包者可以选择默认不安装这些命令,只要在调用时,它们提供有关如何在该平台上安装它们的清晰而简单的说明(通常使用系统包管理器)。
文档更改
作为此更改的一部分,文档的 安装 Python 模块 和 分发 Python 模块 部分已完全重新设计为简短的入门和常见问题解答文档。 大多数打包文档现在已移出到 Python Packaging Authority 维护的 Python Packaging User Guide 和各个项目的文档。
但是,由于此迁移目前仍未完成,因此这些指南的旧版本仍可用作 安装 Python 模块(旧版) 和 分发 Python 模块(旧版)。
也可以看看
- PEP 453 – 在 Python 安装中显式引导 pip
- PEP 由 Donald Stufft 和 Nick Coghlan 编写,由 Donald Stufft、Nick Coghlan、Martin von Löwis 和 Ned Deily 实施。
PEP 476:默认情况下为 stdlib http 客户端启用证书验证
PEP 476 更新了 httplib
和使用它的模块,例如 urllib2
和 xmlrpclib
,现在验证服务器提供由平台信任库中的证书颁发机构签署的证书,其主机名与默认请求的主机名相匹配,显着提高了许多应用程序的安全性。 此更改是在 Python 2.7.9 版本中进行的。
对于需要旧的先前行为的应用程序,它们可以传递备用上下文:
import urllib2
import ssl
# This disables all verification
context = ssl._create_unverified_context()
# This allows using a specific certificate for the host, which doesn't need
# to be in the trust store
context = ssl.create_default_context(cafile="/path/to/file.crt")
urllib2.urlopen("https://invalid-cert", context=context)
PEP 493:适用于 Python 2.7 的 HTTPS 验证迁移工具
PEP 493 提供了额外的迁移工具,以支持包含应用程序和服务的环境的更多增量基础设施升级过程,这些应用程序和服务在建立客户端 HTTPS 连接时依赖于历史上允许的服务器证书处理。 这些添加是在 Python 2.7.12 版本中添加的。
这些工具旨在用于无法修改受影响的应用程序和服务以在建立连接时显式传递更宽松的 SSL 上下文的情况。
对于根本无法修改的应用程序和服务,新的 PYTHONHTTPSVERIFY
环境变量可以设置为 0
以将整个 Python 进程恢复到 Python 2.7.8 的默认许可行为和更早。
对于无法修改连接建立代码,但整体应用可以的情况,可以使用新的ssl._https_verify_certificates()
函数在运行时调整默认行为。
新的 make regen-all 构建目标
为了简化交叉编译,并确保在不需要现有 Python 版本可用的情况下可靠地编译 CPython,基于自动工具的构建系统不再尝试根据文件修改时间隐式地重新编译生成的文件。
相反,添加了一个新的 make regen-all
命令以在需要时强制重新生成这些文件(例如 在已经基于预先生成的版本构建了 Python 的初始版本之后)。
还定义了更多选择性的再生目标 - 有关详细信息,请参阅 :source:`Makefile.pre.in`。
(由 Victor Stinner 在 中提供:问题:`23404`。)
2.7.14 版中的新功能。
移除 make touch 构建目标
make touch
构建目标以前用于通过更新修改时间请求隐式重新生成生成的文件已被删除。
它已被新的 make regen-all
目标取代。
(由 Victor Stinner 在 中提供:问题:`23404`。)
在 2.7.14 版中更改。
致谢
作者要感谢以下人员对本文的各种草稿提供建议、更正和帮助:Nick Coghlan、Philip Jenvey、Ryan Lovett、R. 大卫·默里、休·塞克-沃克。