Python 2.7 中的新功能

作者:

A.M. Kuchling (amk at amk.ca)

本文介绍了 Python 2.7 中的新功能。 Python 2.7 于 2010 年 7 月 3 日发布。

数值处理在许多方面都得到了改进,包括浮点数和 Decimal 类。标准库中添加了一些有用的功能,例如大大增强的 unittest 模块,用于解析命令行选项的 argparse 模块,OrderedDictCounter 等方便的类(在 collections 模块中),以及许多其他改进。

Python 2.7 计划成为 2.x 系列的最后一个版本,因此我们致力于使其成为一个长期的良好版本。 为了帮助移植到 Python 3,Python 3.x 系列中的一些新功能已包含在 2.7 中。

本文不打算提供新功能的完整规范,而是提供一个方便的概述。 有关完整详细信息,您应该参考 https://docs.pythonlang.cn 上的 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 包索引(直接或通过重新分发商)对于 Python 2 用户变得越来越重要。 除了用于各种任务的各种第三方软件包外,可用的软件包还包括与 Python 2 兼容的 Python 3 标准库中新模块和功能的向后移植,以及各种可以更容易迁移到 Python 3 的工具和库。 Python 打包用户指南提供了有关从 Python 包索引下载和安装软件的指导。

  • 虽然增强 Python 2 的首选方法现在是在 Python 包索引上发布新软件包,但这种方法并非在所有情况下都有效,特别是与网络安全相关的那些情况。 在无法通过在 PyPI 上发布新的或更新的软件包来充分处理的特殊情况下,可以使用 Python 增强提案流程来论证将新功能直接添加到 Python 2 标准库中。 任何此类添加以及添加这些添加的维护版本都将在下面的 添加到 Python 2.7 维护版本的新功能 部分中注明。

对于希望从 Python 2 迁移到 Python 3 的项目,或者对于希望支持 Python 2 和 Python 3 用户的库和框架开发人员,有各种工具和指南可帮助决定合适的方法并管理所涉及的一些技术细节。 建议的起点是 如何将 Python 2 代码移植到 Python 3 HOWTO 指南。

弃用警告的处理更改

对于 Python 2.7,做出了一个策略决定,默认情况下仅抑制对开发人员感兴趣的警告。 除非另有要求,否则现在会忽略 DeprecationWarning 及其后代,从而防止用户看到由应用程序触发的警告。 此更改也在成为 Python 3.2 的分支中进行。(在 stdlib-sig 上讨论并在 bpo-7319 中执行。)

在之前的版本中,默认启用 DeprecationWarning 消息,为 Python 开发人员提供了一个明确的指示,说明他们的代码在未来的 Python 主要版本中可能会在哪里中断。

但是,越来越多的 Python 应用程序用户没有直接参与这些应用程序的开发。 DeprecationWarning 消息与此类用户无关,这使得他们担心实际上工作正常的应用程序,并给应用程序开发人员带来了回应这些担忧的负担。

您可以通过使用 -Wdefault(简写形式:-Wd)开关运行 Python,或者在运行 Python 之前将 PYTHONWARNINGS 环境变量设置为 "default"(或 "d")来重新启用 DeprecationWarning 消息的显示。 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:向 collections 添加有序字典 中描述的有序字典类型。

  • PEP 378:千位分隔符的格式说明符 中描述的新 "," 格式说明符。

  • memoryview 对象。

  • importlib 模块的一个小子集,如下所述

  • 浮点数 xrepr() 在许多情况下会更短:它现在基于保证能四舍五入回 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:向 collections 添加有序字典

常规 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* 为 true,则返回并删除最近添加的键;如果为 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 模块默认使用它们,这意味着现在可以以原始顺序读取、修改然后写回配置文件。

  • _asdict() 方法适用于 collections.namedtuple(),现在返回一个有序字典,其中的值以与底层元组索引相同的顺序显示。

  • json 模块的 JSONDecoder 类构造函数扩展了一个 *object_pairs_hook* 参数,以允许解码器构建 OrderedDict 实例。还添加了对 PyYAML 等第三方工具的支持。

另请参阅

PEP 372 - 向 collections 添加有序字典

由 Armin Ronacher 和 Raymond Hettinger 撰写 PEP;由 Raymond Hettinger 实现。

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 378 - 千位分隔符的格式说明符

由 Raymond Hettinger 撰写 PEP;由 Eric Smith 实现。

PEP 389:用于解析命令行的 argparse 模块

添加了用于解析命令行参数的 argparse 模块,以更强大地替代 optparse 模块。

这意味着 Python 现在支持三个不同的模块来解析命令行参数:getoptoptparseargparsegetopt 模块与 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']}

argparseoptparse 拥有更强大的验证功能;你可以指定一个精确的参数数量(使用整数),使用 '*' 表示 0 个或多个参数,使用 '+' 表示 1 个或多个参数,或使用 '?' 表示一个可选参数。顶层解析器可以包含子解析器,用于定义具有不同开关的子命令,例如 svn commitsvn checkout 等。你可以将参数的类型指定为 FileType,它会自动为你打开文件,并且知道 '-' 表示标准输入或输出。

另请参阅

argparse 文档

argparse 模块的文档页面。

将 optparse 代码迁移到 argparse

Python 文档的一部分,描述了如何转换使用 optparse 的代码。

PEP 389 - argparse - 新的命令行解析模块

由 Steven Bethard 编写和实现的 PEP。

PEP 391:基于字典的日志配置

logging 模块非常灵活;应用程序可以定义一个日志子系统的树形结构,并且此树中的每个记录器都可以过滤掉某些消息,以不同的方式格式化它们,并将消息定向到不同数量的处理程序。

所有这些灵活性可能需要大量的配置。你可以编写 Python 语句来创建对象并设置它们的属性,但是复杂的设置需要冗长而枯燥的代码。logging 还支持 fileConfig() 函数来解析文件,但是文件格式不支持配置过滤器,并且以编程方式生成它更加混乱。

Python 2.7 添加了一个 dictConfig() 函数,该函数使用字典来配置日志。有很多方法可以从不同的来源生成字典:使用代码构造一个;解析包含 JSON 的文件;如果安装了 YAML 解析库,则使用它。有关更多信息,请参见 配置函数

以下示例配置了两个记录器,根记录器和一个名为“network”的记录器。发送到根记录器的消息将使用 syslog 协议发送到系统日志,而发送到“network”记录器的消息将写入 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 进行 syslog 记录。构造函数有一个 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() 方法,该方法接受一个 level 参数,并返回底层记录器是否会处理该重要级别的消息。

另请参阅

PEP 391 - 基于字典的日志配置

由 Vinay Sajip 编写和实现的 PEP。

PEP 3106:字典视图

字典方法 keys()values()items() 在 Python 3.x 中有所不同。它们返回一个名为视图的对象,而不是完全物化的列表。

在 Python 2.7 中,不可能更改 keys()values()items() 的返回值,因为太多代码会因此中断。相反,3.x 版本以新名称 viewkeys()viewvalues()viewitems() 添加。

>>> 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;bpo-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;bpo-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 向后移植;bpo-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 向后移植;bpo-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() 用于浮点数和复数;floatcomplex 构造函数;数值格式化;使用 marshalpicklejson 模块序列化和反序列化浮点数和复数;解析 Python 代码中的浮点数和虚数字面量;以及 Decimal 到浮点数的转换。

    与此相关,浮点数 *x* 的 repr() 现在返回基于最短十进制字符串的结果,该字符串保证在正确的舍入(使用四舍五入到偶数的舍入模式)下舍入回 *x*。 以前它给出了一个基于将 x 舍入到 17 位小数的字符串。

    负责此改进的舍入库在 Windows 和使用 gcc、icc 或 suncc 编译器的 Unix 平台上工作。可能存在少数无法保证此代码正确运行的平台,因此该代码未在这些系统上使用。您可以通过检查 sys.float_repr_style 来了解正在使用哪个代码,如果正在使用新代码,则该值将为 short,如果未使用,则为 legacy

    由 Eric Smith 和 Mark Dickinson 使用 David Gay 的 dtoa.c 库实现;bpo-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 实现;bpo-3166。)

    整数除法在其舍入行为中也更准确。(也由 Mark Dickinson 实现;bpo-1811。)

  • 复数的隐式强制类型转换已被删除;解释器将不再尝试在复数对象上调用 __coerce__() 方法。(由 Meador Inge 和 Mark Dickinson 删除;bpo-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 贡献;bpo-5237。)

    复数现在正确地支持与 format() 一起使用,并且默认右对齐。指定精度或逗号分隔符适用于数字的实部和虚部,但指定的字段宽度和对齐方式适用于整个结果 1.5+3j 输出。(由 Eric Smith 贡献;bpo-1588bpo-7988。)

    “F”格式代码现在始终使用大写字符格式化其输出,因此现在将生成“INF”和“NAN”。(由 Eric Smith 贡献;bpo-3382。)

    一个低级更改:如果向 object.__format__() 方法传递格式字符串,则该方法现在会触发 PendingDeprecationWarning,因为 object__format__() 方法将对象转换为字符串表示形式并格式化该字符串。以前,该方法会默默地将格式字符串应用于字符串表示形式,但这可能会隐藏 Python 代码中的错误。 如果您提供诸如对齐或精度之类的格式化信息,则可能希望以某种特定于对象的方式应用格式化。(由 Eric Smith 修复;bpo-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 贡献;bpo-3439。)

  • 如果相对导入(例如 from .os import sep)失败,import 语句将不再尝试绝对导入。这修复了一个错误,但可能会破坏某些只是偶然起作用的 import 语句。(由 Meador Inge 修复;bpo-7902。)

  • 现在,内置 unicode 类型的子类可以重写 __unicode__() 方法。(由 Victor Stinner 实现;bpo-1583863。)

  • bytearray 类型的 translate() 方法现在接受 None 作为其第一个参数。(由 Georg Brandl 修复;bpo-4759。)

  • 当使用 @classmethod@staticmethod 将方法包装为类方法或静态方法时,包装器对象现在将其包装的函数公开为它们的 __func__ 属性。(由 Amaury Forgeot d’Arc 贡献,在 George Sakkis 的建议之后;bpo-5982。)

  • 当使用 __slots__ 设置了受限的属性集时,删除未设置的属性不会像预期那样引发 AttributeError。由 Benjamin Peterson 修复;bpo-7604。)

  • 现在支持两种新的编码:“cp720”,主要用于阿拉伯文本;以及“cp858”,它是 CP 850 的变体,添加了欧元符号。(CP720 由 Alexander Belchenko 和 Amaury Forgeot d’Arc 在 bpo-1616979 中贡献;CP858 由 Tim Hatch 在 bpo-8016 中贡献。)

  • 现在,当尝试在 POSIX 平台上打开目录时,file 对象将在 IOError 异常上设置 filename 属性(由 Jan Kaliszewski 指出;bpo-4764),并且现在显式检查并禁止写入只读文件对象,而不是信任 C 库来捕获和报告错误(由 Stefan Krah 修复;bpo-5677)。

  • Python 词法分析器现在自行转换行尾符,因此 compile() 内置函数现在接受使用任何行尾约定的代码。此外,它不再要求代码以换行符结尾。

  • 函数定义中的额外括号在 Python 3.x 中是非法的,这意味着你会从 def f((x)): pass 中得到一个语法错误。在 Python3 警告模式下,Python 2.7 现在将警告这种奇怪的用法。(由 James Lingard 指出;bpo-7362。)

  • 现在可以创建对旧式类对象的弱引用。新式类始终是可弱引用的。(由 Antoine Pitrou 修复;bpo-8268。)

  • 当模块对象被垃圾回收时,如果其他人没有持有对该模块字典的引用,则现在才清除该模块的字典(bpo-7140)。

解释器变更

一个新的环境变量,PYTHONWARNINGS,允许控制警告。它应该被设置为包含警告设置的字符串,等同于与 -W 开关一起使用的警告设置,用逗号分隔。(由 Brian Curtin 贡献;bpo-7301。)

例如,以下设置将在每次发生警告时打印警告,但将 Cookie 模块中的警告转换为错误。(设置环境变量的确切语法因操作系统和 shell 而异。)

export PYTHONWARNINGS=all,error:::Cookie:0

优化

添加了几项性能增强

  • 添加了一个新的操作码,用于执行 with 语句的初始设置,查找 __enter__()__exit__() 方法。(由 Benjamin Peterson 贡献。)

  • 垃圾收集器现在对于一种常见的用法模式表现更好:当分配了许多对象而没有释放任何对象时。以前,这需要二次时间进行垃圾回收,但现在,随着堆上对象数量的增长,完全垃圾回收的次数减少了。只有当中间代被收集 10 次并且中间代的幸存对象数量超过最老一代对象数量的 10% 时,新逻辑才会执行完全垃圾回收过程。(由 Martin von Löwis 提出建议,并由 Antoine Pitrou 实现;bpo-4074。)

  • 垃圾收集器会尽量避免跟踪不能成为循环一部分的简单容器。在 Python 2.7 中,现在对于包含原子类型(例如整数、字符串等)的元组和字典来说是这样的。传递地,包含原子类型元组的字典也不会被跟踪。这有助于减少每次垃圾回收的成本,因为减少了收集器需要考虑和遍历的对象数量。(由 Antoine Pitrou 贡献;bpo-4688。)

  • 长整数现在在内部存储为基数 2**15 或基数 2**30,基数在构建时确定。以前,它们总是以基数 2**15 存储。在 64 位机器上使用基数 2**30 可以显著提高性能,但在 32 位机器上的基准测试结果好坏参半。因此,默认是在 64 位机器上使用基数 2**30,在 32 位机器上使用基数 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 贡献;bpo-4258。)

    另一组更改使长对象小了几字节:在 32 位系统上小 2 字节,在 64 位系统上小 6 字节。(由 Mark Dickinson 贡献;bpo-5260。)

  • 通过收紧内循环,进行移位而不是乘法,并修复一个不必要的额外迭代,长整数的除法算法变得更快了。各种基准测试显示,长整数除法和模运算的速度提高了 50% 到 150% 之间。(由 Mark Dickinson 贡献;bpo-5512。)按位运算也明显更快(最初由 Gregory Smith 提供补丁;bpo-1087418)。

  • % 的实现检查左侧操作数是否为 Python 字符串,并对其进行特殊处理;这使得频繁使用带有字符串的 % 的应用程序(例如模板库)的性能提高了 1-3%。(由 Collin Winter 实现;bpo-5176。)

  • 带有 if 条件的列表推导式被编译为更快的字节码。(由 Antoine Pitrou 提供补丁,由 Jeffrey Yasskin 反向移植到 2.7;bpo-4715。)

  • 通过特殊处理基数 10 而不是使用支持任意基数的通用转换函数,将整数或长整数转换为十进制字符串的速度加快了。(由 Gawain Bolton 提供补丁;bpo-6713。)

  • 类字符串类型(字符串、Unicode 字符串和 bytearray 对象)的 split()replace()rindex()rpartition()rsplit() 方法现在使用快速反向搜索算法,而不是逐字符扫描。这有时会快 10 倍。(由 Florent Xicluna 添加;bpo-7462bpo-7622。)

  • picklecPickle 模块现在会自动实习用于属性名称的字符串,从而减少了取消腌制产生的对象的内存使用量。(由 Jake McGuire 贡献;bpo-5084。)

  • cPickle 模块现在特殊处理字典,几乎将腌制它们所需的时间减半。(由 Collin Winter 贡献;bpo-5670。)

新的和改进的模块

与每个版本一样,Python 的标准库收到了许多增强功能和错误修复。以下是按模块名称字母顺序排列的最显著更改的部分列表。有关更完整的更改列表,请查阅源代码树中的 Misc/NEWS 文件,或浏览 Subversion 日志以获取所有详细信息。

  • bdb 模块的基础调试类 Bdb 获得了一个跳过模块的功能。现在,构造函数接受一个包含 glob 样式模式(例如 django.*)的可迭代对象;调试器将不会进入与这些模式之一匹配的模块中的堆栈帧。(由 Maru Newby 在 Senthil Kumaran 的建议后贡献;bpo-5142。)

  • 现在,binascii 模块支持缓冲区 API,因此它可以与 memoryview 实例和其他类似的缓冲区对象一起使用。(由 Florent Xicluna 从 3.x 版本移植;bpo-7703.)

  • 已更新的模块:bsddb 模块已从 4.7.2devel9 更新到 pybsddb 包的 4.8.4 版本。新版本具有更好的 Python 3.x 兼容性,修复了各种错误,并添加了几个新的 BerkeleyDB 标志和方法。(由 Jesús Cea Avión 更新;bpo-8156。pybsddb 的更新日志可以在 https://hg.jcea.es/pybsddb/file/tip/ChangeLog 中阅读。)

  • bz2 模块的 BZ2File 现在支持上下文管理协议,因此您可以编写 with bz2.BZ2File(...) as f:。(由 Hagen Fürstenau 贡献;bpo-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 贡献;bpo-1696199

    新类:OrderedDict 在前面的 PEP 372:向 collections 添加有序字典 部分中进行了描述。

    新方法:deque 数据类型现在有一个 count() 方法,该方法返回包含的元素中等于提供的参数 *x* 的数量,以及一个 reverse() 方法,该方法就地反转 deque 的元素。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 添加;bpo-1818.)

    最后,如果将映射与不是 Mapping 的另一种类型进行比较,则 Mapping 抽象基类现在返回 NotImplemented。(由 Daniel Stutzbach 修复;bpo-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 贡献;bpo-7005.)

  • 已弃用的函数:contextlib.nested(),它允许使用单个 with 语句处理多个上下文管理器,已被弃用,因为 with 语句现在支持多个上下文管理器。

  • 现在,cookielib 模块会忽略具有无效版本字段(不包含整数值的字段)的 cookie。(由 John J. Lee 修复;bpo-3924.)

  • 现在,copy 模块的 deepcopy() 函数将正确复制绑定的实例方法。(由 Robert Collins 实现;bpo-1515.)

  • 现在,对于声明为指针的参数,ctypes 模块始终将 None 转换为 C NULL 指针。(由 Thomas Heller 更改;bpo-4606.) 底层的 libffi 库已更新到 3.0.9 版本,其中包含针对不同平台的各种修复。(由 Matthias Klose 更新;bpo-8142.)

  • 新方法:datetime 模块的 timedelta 类获得了一个 total_seconds() 方法,该方法返回持续时间中的秒数。(由 Brian Quinlan 贡献;bpo-5788.)

  • 新方法:Decimal 类获得了一个 from_float() 类方法,该方法将浮点数精确转换为 Decimal。此精确转换力求获得最接近浮点数表示值的十进制近似值;因此,如果存在任何不准确之处,则生成的十进制值仍将包含该不准确之处。例如,Decimal.from_float(0.1) 返回 Decimal('0.1000000000000000055511151231257827021181583404541015625')。(由 Raymond Hettinger 实现;bpo-4796.)

    现在,将 Decimal 的实例与浮点数进行比较会基于操作数的数值产生合理的结果。以前,此类比较会退回到 Python 比较对象的默认规则,该规则会根据它们的类型产生任意的结果。请注意,您仍然不能在加法等其他操作中组合 Decimal 和浮点数,因为您应该显式地选择如何在浮点数和 Decimal 之间进行转换。(由 Mark Dickinson 修复;bpo-2531。)

    Decimal 的构造函数现在接受浮点数(由 Raymond Hettinger 添加;bpo-8257)和非欧洲 Unicode 字符,例如阿拉伯-印度数字(由 Mark Dickinson 贡献;bpo-6595)。

    Context 类的大多数方法现在接受整数以及 Decimal 实例;唯一的例外是 canonical()is_canonical() 方法。(Juan José Conti 的补丁;bpo-7633。)

    当使用 Decimal 实例与字符串的 format() 方法时,默认对齐方式以前是左对齐。这已更改为右对齐,对于数值类型来说更合理。(由 Mark Dickinson 更改;bpo-6857。)

    涉及信号 NaN 值(或 sNAN)的比较现在会发出 InvalidOperation 信号,而不是根据比较运算符静默地返回 true 或 false 值。现在,安静的 NaN 值(或 NaN)是可哈希的。(由 Mark Dickinson 修复;bpo-7279。)

  • difflib 模块现在通过一个小的更改,在给出文件名的标头中使用制表符而不是空格作为分隔符,从而产生与现代 diff/patch 工具更兼容的输出。(由 Anatoly Techtonik 修复;bpo-7585。)

  • Distutils sdist 命令现在始终重新生成 MANIFEST 文件,因为即使 MANIFEST.insetup.py 文件没有被修改,用户也可能创建了一些应该包含的新文件。(由 Tarek Ziadé 修复;bpo-8688。)

  • doctest 模块的 IGNORE_EXCEPTION_DETAIL 标志现在将忽略包含正在测试的异常的模块名称。(Lennart Regebro 的补丁;bpo-7490。)

  • email 模块的 Message 类现在将接受 Unicode 值的有效负载,自动将有效负载转换为 output_charset 指定的编码。(由 R. David Murray 添加;bpo-1368247。)

  • Fraction 类现在接受单个浮点数或 Decimal 实例,或两个有理数,作为其构造函数的参数。(由 Mark Dickinson 实现;有理数在 bpo-5812 中添加,浮点数/十进制数在 bpo-8294 中添加。)

    分数和复数之间的排序比较(<<=>>=)现在会引发 TypeError。这修复了一个疏忽,使 Fraction 与其他数值类型匹配。

  • 新类:FTP_TLSftplib 模块中提供了安全的 FTP 连接,使用 TLS 封装身份验证以及后续的控制和数据传输。(由 Giampaolo Rodola 贡献;bpo-2054。)

    用于二进制上传的 storbinary() 方法现在可以通过添加的 rest 参数来重新启动上传(Pablo Mouzo 的补丁;bpo-6845。)

  • 新的类装饰器:total_ordering()functools 模块中,接受一个定义了 __eq__() 方法和 __lt__()__le__()__gt__()__ge__() 之一的类,并生成缺少的比较方法。由于 __cmp__() 方法在 Python 3.x 中被弃用,此装饰器使定义有序类更加容易。(由 Raymond Hettinger 添加;bpo-5479。)

    新函数:cmp_to_key() 将接受一个期望两个参数的旧式比较函数,并返回一个新的可调用对象,该对象可用作 sorted()min()max() 等函数的 key 参数。 主要用途是帮助使代码与 Python 3.x 兼容。(由 Raymond Hettinger 添加。)

  • 新函数:gc 模块的 is_tracked() 函数返回给定实例是否由垃圾收集器跟踪,否则返回 false。(由 Antoine Pitrou 贡献;bpo-4688。)

  • gzip 模块的 GzipFile 现在支持上下文管理协议,因此您可以编写 with gzip.GzipFile(...) as f: (由 Hagen Fürstenau 贡献;bpo-3860),并且它现在实现了 io.BufferedIOBase ABC,因此您可以使用 io.BufferedReader 对其进行包装以进行更快的处理(由 Nir Aides 贡献;bpo-7471)。现在还可以通过向构造函数提供可选的时间戳来覆盖 gzipped 文件中记录的修改时间。(由 Jacques Frechet 贡献;bpo-4272。)

    gzip 格式的文件可以使用尾部零字节进行填充;gzip 模块现在会消耗这些尾部字节。(由 Tadek Pietraszek 和 Brian Curtin 修复;bpo-2846。)

  • 新属性:hashlib 模块现在有一个 algorithms 属性,其中包含一个元组,该元组命名了支持的算法。在 Python 2.7 中,hashlib.algorithms 包含 ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')。(由 Carl Chenet 贡献;bpo-7418。)

  • httplib 模块使用的默认 HTTPResponse 类现在支持缓冲,从而可以更快地读取 HTTP 响应。(由 Kristján Valur Jónsson 贡献;bpo-4879。)

    HTTPConnectionHTTPSConnection 类现在支持 source_address 参数,这是一个 (host, port) 二元组,用于指定连接将使用的源地址。(由 Eldon Ziegler 贡献;bpo-3972。)

  • ihooks 模块现在支持相对导入。请注意,ihooks 是一个用于自定义导入的较旧模块,已被 Python 2.0 中添加的 imputil 模块取代。(相对导入支持由 Neil Schemenauer 添加。)

  • imaplib 模块现在支持 IPv6 地址。(由 Derek Morr 贡献;bpo-1655。)

  • 新函数:inspect 模块的 getcallargs() 函数接受一个可调用对象及其位置参数和关键字参数,并找出可调用对象的哪些参数将接收每个参数,返回一个将参数名称映射到其值的字典。例如

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

    由 George Sakkis 贡献;bpo-3135

  • 更新的模块:io 库已升级到 Python 3.1 随附的版本。对于 3.1,I/O 库完全用 C 语言重写,其速度根据所执行的任务提高了 2 到 20 倍。原始的 Python 版本已重命名为 _pyio 模块。

    一个小的相关更改:io.TextIOBase 类现在有一个 errors 属性,该属性给出了用于编码和解码错误的错误设置('strict''replace''ignore' 中的一个)。

    现在,当传递无效的文件描述符时,io.FileIO 类会引发 OSError。(由 Benjamin Peterson 实现;bpo-4991。)truncate() 方法现在会保留文件位置;以前,它会将文件位置更改为新文件的末尾。(由 Pascal Chambon 修复;bpo-6939。)

  • 新函数:itertools.compress(data, selectors) 接受两个迭代器。如果 selectors 中的相应值为 true,则返回 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 实现;bpo-5032。)

    对于大于输入可迭代对象的 r 值,itertools.combinations()itertools.product() 以前会引发 ValueError。这被认为是规范错误,因此它们现在返回一个空迭代器。(由 Raymond Hettinger 修复;bpo-4816。)

  • 更新的模块:json 模块已升级到 simplejson 包的 2.0.9 版本,其中包括一个 C 扩展,可加快编码和解码速度。(由 Bob Ippolito 贡献;bpo-4136。)

    为了支持新的 collections.OrderedDict 类型,json.load() 现在有一个可选的 object_pairs_hook 参数,该参数将在任何解码为成对列表的对象文字时被调用。(由 Raymond Hettinger 贡献;bpo-5381。)

  • mailbox 模块的 Maildir 类现在会记录它读取的目录的时间戳,并且仅当修改时间随后发生更改时才会重新读取它们。这通过避免不必要的目录扫描来提高性能。(由 A.M. Kuchling 和 Antoine Pitrou 修复;bpo-1607951bpo-6896。)

  • 新函数:math 模块获得了用于误差函数和互补误差函数的 erf()erfc(),计算 e**x - 1expm1() 比使用 exp() 并减去 1 具有更高的精度,用于 Gamma 函数的 gamma(),以及用于 Gamma 函数自然对数的 lgamma()。(由 Mark Dickinson 和 nirinA raseliarison 贡献;bpo-3366。)

  • multiprocessing 模块的 Manager* 类现在可以传递一个可调用对象,该对象将在每次启动子进程时被调用,以及一组将传递给可调用对象的参数。(由 lekma 贡献;bpo-5585。)

    控制工作进程池的 Pool 类现在有一个可选的 maxtasksperchild 参数。工作进程将执行指定数量的任务,然后退出,从而使 Pool 启动新的工作进程。如果任务可能会泄漏内存或其他资源,或者某些任务会导致工作进程变得非常大,则此功能很有用。(由 Charles Cazabon 贡献;bpo-6963。)

  • 现在 nntplib 模块支持 IPv6 地址。(由 Derek Morr 贡献;bpo-1664。)

  • 新增函数:os 模块封装了以下 POSIX 系统调用:getresgid()getresuid(),它们返回真实的、有效的和保存的 GID 和 UID;setresgid()setresuid(),它们将真实的、有效的和保存的 GID 和 UID 设置为新值;initgroups(),它初始化当前进程的组访问列表。(GID/UID 函数由 Travis H. 贡献;bpo-6508。initgroups 的支持由 Jean-Paul Calderone 添加;bpo-7333。)

    os.fork() 函数现在在子进程中重新初始化导入锁;这修复了在从线程调用 fork() 时在 Solaris 上出现的问题。(由 Zsolt Cserna 修复;bpo-7242。)

  • os.path 模块中,normpath()abspath() 函数现在保留 Unicode;如果它们的输入路径是 Unicode 字符串,则返回值也是 Unicode 字符串。( normpath() 由 Matt Giuca 在 bpo-5827 中修复;abspath() 由 Ezio Melotti 在 bpo-3426 中修复。)

  • pydoc 模块现在提供 Python 使用的各种符号的帮助。 例如,您现在可以执行 help('<<')help('@')。(由 David Laban 贡献;bpo-4739。)

  • re 模块的 split()sub()subn() 现在接受一个可选的 flags 参数,以便与模块中的其他函数保持一致。(由 Gregory P. Smith 添加。)

  • 新增函数:run_path()runpy 模块中,它将执行提供的 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 添加;bpo-6816。)

  • 新增函数:在 shutil 模块中,make_archive() 接受文件名、存档类型(zip 或 tar 格式)和目录路径,并创建一个包含目录内容的存档。(由 Tarek Ziadé 添加。)

    shutilcopyfile()copytree() 函数现在在被要求复制命名管道时会引发 SpecialFileError 异常。以前,该代码会像处理常规文件一样,打开命名管道进行读取,并且会无限期地阻塞。(由 Antoine Pitrou 修复;bpo-3002。)

  • signal 模块不再重新安装信号处理程序,除非真正需要这样做,这修复了一个可能导致无法可靠地捕获 EINTR 信号的错误。(由 Charles-Francois Natali 修复;bpo-8354。)

  • 新增函数:在 site 模块中,三个新函数返回各种特定于站点和用户的路径。getsitepackages() 返回包含所有全局 site-packages 目录的列表,getusersitepackages() 返回用户 site-packages 目录的路径,并且 getuserbase() 返回 USER_BASE 环境变量的值,给出可用于存储数据的目录的路径。(由 Tarek Ziadé 贡献;bpo-6693。)

    site 模块现在报告在导入 sitecustomize 模块时发生的异常,并且将不再捕获和吞噬 KeyboardInterrupt 异常。(由 Victor Stinner 修复;bpo-3137。)

  • create_connection() 函数增加了一个 source_address 参数,这是一个 (host, port) 二元组,它给出了将用于连接的源地址。(由 Eldon Ziegler 贡献;bpo-3972。)

    现在,recv_into()recvfrom_into() 方法可以将数据写入支持缓冲区 API 的对象中,最常用的就是 bytearraymemoryview 对象。(由 Antoine Pitrou 实现;bpo-8104。)

  • SocketServer 模块的 TCPServer 类现在支持套接字超时和禁用 Nagle 算法。disable_nagle_algorithm 类属性默认为 False;如果覆盖为 true,新的请求连接将设置 TCP_NODELAY 选项,以防止将多个小的发送操作缓冲到一个 TCP 数据包中。timeout 类属性可以保存一个以秒为单位的超时时间,该超时时间将应用于请求套接字;如果在该时间内没有收到任何请求,则会调用 handle_timeout(),并且 handle_request() 将返回。(由 Kristján Valur Jónsson 贡献;bpo-6192bpo-6267。)

  • 更新的模块:sqlite3 模块已更新到 pysqlite 包的 2.6.0 版本。2.6.0 版本包括许多错误修复,并增加了从共享库加载 SQLite 扩展的功能。调用 enable_load_extension(True) 方法来启用扩展,然后调用 load_extension() 来加载特定的共享库。(由 Gerhard Häring 更新。)

  • ssl 模块的 SSLSocket 对象现在支持缓冲区 API,这修复了一个测试套件失败的问题(由 Antoine Pitrou 修复;bpo-7133),并自动设置 OpenSSL 的 SSL_MODE_AUTO_RETRY,这将防止在触发 SSL 重新协商时从 recv() 操作返回错误代码(由 Antoine Pitrou 修复;bpo-8222)。

    现在,wrap_socket() 构造函数接受一个 ciphers 参数,该参数是一个字符串,列出了允许使用的加密算法;该字符串的格式在OpenSSL 文档中进行了描述。(由 Antoine Pitrou 添加;bpo-8322。)

    另一个更改使扩展加载所有 OpenSSL 的密码和摘要算法,以便它们都可用。某些 SSL 证书无法验证,并报告“未知算法”错误。(由 Beda Kosata 报告,并由 Antoine Pitrou 修复;bpo-8484。)

    现在,所使用的 OpenSSL 版本可通过模块属性 ssl.OPENSSL_VERSION(字符串)、ssl.OPENSSL_VERSION_INFO(5 元组)和 ssl.OPENSSL_VERSION_NUMBER(整数)获得。(由 Antoine Pitrou 添加;bpo-8321。)

  • 当值对于特定的整数格式代码(bBhHiIlLqQ 之一)来说太大时,struct 模块将不再静默地忽略溢出错误;现在,它总是引发 struct.error 异常。(由 Mark Dickinson 更改;bpo-1523。)在尝试 __int__() 方法或报告错误之前,pack() 函数还将尝试使用 __index__() 来转换和打包非整数。(由 Mark Dickinson 更改;bpo-8300。)

  • 新函数:subprocess 模块的 check_output() 使用指定的参数集运行命令,并在命令无错误运行时返回命令的输出作为字符串,否则会引发 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
    

    (由 Gregory P. Smith 贡献。)

    现在,subprocess 模块在接收到 EINTR 信号时将重试其内部系统调用。(由多人报告;由 Gregory P. Smith 在 bpo-1068268 中最终修复。)

  • 新函数:is_declared_global()symtable 模块中,对于显式声明为全局的变量返回 true,对于隐式全局的变量返回 false。(由 Jeremy Hylton 贡献。)

  • 现在,syslog 模块将使用 sys.argv[0] 的值作为标识符,而不是之前的默认值 'python'。(由 Sean Reifschneider 更改;bpo-8451。)

  • 现在,sys.version_info 值是一个命名元组,其属性名为 majorminormicroreleaselevelserial。(由 Ross Light 贡献;bpo-4285。)

    sys.getwindowsversion() 也返回一个命名元组,其属性名为 majorminorbuildplatformservice_packservice_pack_majorservice_pack_minorsuite_maskproduct_type。(由 Brian Curtin 贡献;bpo-7766。)

  • tarfile 模块的默认错误处理已更改,不再抑制致命错误。之前的默认错误级别为 0,这意味着错误只会导致将消息写入调试日志,但由于默认情况下未激活调试日志,因此这些错误会被忽略。现在的默认错误级别为 1,如果发生错误,则会引发异常。(由 Lars Gustäbel 更改;bpo-7357。)

    tarfile 现在支持过滤添加到 tar 文件中的 TarInfo 对象。当您调用 add() 时,您可以提供一个可选的 *filter* 参数,它是一个可调用对象。该 *filter* 可调用对象将传递正在添加的每个文件的 TarInfo,并且可以修改并返回它。如果可调用对象返回 None,则该文件将从生成的存档中排除。这比现有的 *exclude* 参数更强大,因此该参数已被弃用。(由 Lars Gustäbel 添加;bpo-6856。) TarFile 类现在也支持上下文管理协议。(由 Lars Gustäbel 添加;bpo-7232。)

  • wait() 方法,属于 threading.Event 类,现在在退出时返回内部标志。这意味着该方法通常会返回 true,因为 wait() 应该会阻塞,直到内部标志变为 true。仅当提供了超时并且操作超时时,返回值才会为 false。(由 Tim Lesher 贡献;bpo-1674032。)

  • unicodedata 模块提供的 Unicode 数据库现在在内部用于确定哪些字符是数字、空格或表示换行符。该数据库还包括来自 Unihan.txt 数据文件的信息(由 Anders Chrigström 和 Amaury Forgeot d'Arc 提供补丁;bpo-1571184),并已更新到 5.2.0 版本(由 Florent Xicluna 更新;bpo-8024)。

  • urlparse 模块的 urlsplit() 现在以符合 RFC 3986 的方式处理未知的 URL 方案:如果 URL 的形式为 "<something>://...",则将 :// 前的文本视为方案,即使它是一个模块不知道的虚构方案。此更改可能会破坏绕过旧行为的代码。例如,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 定义的 IPv6 字面地址(由 Senthil Kumaran 贡献;bpo-2987)。

    >>> urlparse.urlparse('http://[1080::8:800:200C:417A]/foo')
    ParseResult(scheme='http', netloc='[1080::8:800:200C:417A]',
                path='/foo', params='', query='', fragment='')
    
  • 新类: WeakSet 类,在 weakref 模块中,是一个仅保存对其元素的弱引用的集合;一旦没有指向它们的引用,元素将被删除。(最初由 Raymond Hettinger 在 Python 3.x 中实现,并由 Michael Foord 向后移植到 2.7。)

  • xml.etree.ElementTree 库,在输出 XML 处理指令(看起来像 <?xml-stylesheet href="#style1"?>)或注释(看起来像 <!-- comment -->)时,不再转义与号和尖括号。(由 Neil Muller 提供补丁;bpo-2746。)

  • XML-RPC 客户端和服务器,由 xmlrpclibSimpleXMLRPCServer 模块提供,通过支持 HTTP/1.1 keep-alive 和可选地使用 gzip 编码压缩交换的 XML,提高了性能。gzip 压缩由 SimpleXMLRPCRequestHandlerencode_threshold 属性控制,该属性包含一个以字节为单位的大小;大于此值的响应将被压缩。(由 Kristján Valur Jónsson 贡献;bpo-6267。)

  • zipfile 模块的 ZipFile 现在支持上下文管理协议,因此您可以编写 with zipfile.ZipFile(...) as f:。(由 Brian Curtin 贡献;bpo-5511。)

    zipfile 现在还支持存档空目录并正确提取它们。(由 Kuba Wieczorek 修复;bpo-4710。)从存档中读取文件速度更快,并且交错使用 read()readline() 现在可以正常工作。(由 Nir Aides 贡献;bpo-7610。)

    is_zipfile() 函数现在除了接受早期版本中接受的路径名之外,还接受文件对象。(由 Gabriel Genellina 贡献;bpo-4756。)

    writestr() 方法现在有一个可选的 *compress_type* 参数,允许您覆盖 ZipFile 构造函数中指定的默认压缩方法。(由 Ronald Oussoren 贡献;bpo-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 模块文档。您可能还希望阅读 Tcl/Tk 手册页,其中描述了 Ttk 主题引擎,可从 https://www.tcl.tk/man/tcl8.5/TkCmd/ttk_intro.html 获取。Python/Ttk 代码的一些屏幕截图位于 https://code.google.com/archive/p/python-ttk/wikis/Screenshots.wiki

tkinter.ttk 模块由 Guilherme Polo 编写,并在 bpo-2983 中添加。由 Martin Franklin 编写并由 Kevin Walzer 维护的名为 Tile.py 的替代版本被提议包含在 bpo-2618 中,但作者认为 Guilherme Polo 的工作更全面。

更新模块:unittest

unittest 模块得到了极大的增强;添加了许多新功能。除非另有说明,否则这些功能大多由 Michael Foord 实现。该模块的增强版本可以单独下载,用于 Python 版本 2.4 至 2.6,打包为 unittest2 包,来自 unittest2

从命令行使用时,该模块可以自动发现测试。它不如 py.testnose 那样花哨,但提供了一种简单的方法来运行保存在一组包目录中的测试。例如,以下命令将在 test/ 子目录中搜索任何名为 test*.py 的可导入测试文件

python -m unittest discover -s test

有关更多详细信息,请参阅 unittest 模块文档。(在 bpo-6001 中开发。)

main() 函数支持一些其他新选项

  • -b--buffer 将在每个测试期间缓冲标准输出和标准错误流。如果测试通过,则会丢弃任何生成的输出;如果失败,则会显示缓冲的输出。

  • -c--catch 将使 control-C 中断得到更优雅的处理。它不会立即中断测试过程,而是完成当前正在运行的测试,然后报告直到中断为止的部分结果。如果您不耐烦,第二次按下 control-C 将导致立即中断。

    此 control-C 处理程序会尝试避免在被测试的代码或正在运行的测试定义了自己的信号处理程序时引起问题,它会注意到已经设置了信号处理程序并调用它。如果这对您不起作用,则有一个 removeHandler() 修饰符,可用于标记应该禁用 control-C 处理的测试。

  • -f--failfast 使测试执行在测试失败时立即停止,而不是继续执行其他测试。(由 Cliff Dyer 建议并由 Michael Foord 实现;bpo-8074。)

以详细模式运行时,进度消息现在会为预期失败显示“x”,为意外成功显示“u”。(由 Benjamin Peterson 贡献。)

测试用例可以引发 SkipTest 异常来跳过测试(bpo-1034053)。

assertEqual()assertTrue()assertFalse() 失败的错误消息现在提供了更多信息。如果您将 longMessage 属性设置为 TestCase 类的 true,则标准错误消息和您提供的任何其他消息都将在失败时打印。(由 Michael Foord 添加;bpo-5663。)

当在不提供可运行对象的情况下调用时,assertRaises() 方法现在返回一个上下文处理程序。例如,您可以这样写

with self.assertRaises(KeyError):
    {}['foo']

(由 Antoine Pitrou 实现;bpo-4444。)

现在支持模块级和类级 setup 和 teardown fixtures。模块可以包含 setUpModule()tearDownModule() 函数。类可以具有 setUpClass()tearDownClass() 方法,必须将其定义为类方法(使用 @classmethod 或等效方法)。当测试运行器切换到不同模块或类中的测试用例时,将调用这些函数和方法。

添加了方法 addCleanup()doCleanups()addCleanup() 允许您添加清理函数,这些函数将被无条件调用(如果在 setUp() 失败后调用,否则在 tearDown() 之后调用)。这使得测试期间的资源分配和释放更加简单 (bpo-5679)。

添加了许多提供更专业测试的新方法。这些方法中的许多是由谷歌工程师编写的,用于他们的测试套件;Gregory P. Smith、Michael Foord 和 GvR 致力于将它们合并到 Python 版本的 unittest 中。

unittest.main() 现在接受一个可选的 exit 参数。如果为 false,则 main() 不会调用 sys.exit(),从而允许从交互式解释器中使用 main()。(由 J. Pablo Fernández 贡献;bpo-3379。)

TestResult 具有新的 startTestRun()stopTestRun() 方法,这些方法在测试运行之前和之后立即调用。(由 Robert Collins 贡献;bpo-5728。)

随着所有这些更改,unittest.py 变得异常庞大,因此该模块被转换为一个包,并将代码拆分为多个文件(由 Benjamin Peterson 完成)。这不会影响模块的导入或使用方式。

另请参阅

https://web.archive.org/web/20210619163128/http://www.voidspace.org.uk/python/articles/unittest2.shtml

描述了新功能、如何使用它们以及各种设计决策的理由。(作者:Michael Foord。)

更新的模块: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 为 false,但没有子元素的元素也为 false? - 因此现在将触发 FutureWarning。在您的代码中,您应该明确:如果您对子元素的数量感兴趣,请编写 len(elem) != 0,或者编写 elem is not None

Fredrik Lundh 开发了 ElementTree 并制作了 1.3 版本;您可以在 https://web.archive.org/web/20200703234532/http://effbot.org/zone/elementtree-13-intro.htm 上阅读他描述 1.3 的文章。 Florent Xicluna 在 python-dev 和 bpo-6472 的讨论之后更新了 Python 中包含的版本。)

构建和 C API 更改

Python 的构建过程和 C API 的更改包括

  • GNU 调试器 GDB 7 的最新版本可以使用 Python 进行脚本编写。当您开始调试可执行程序 P 时,GDB 将查找名为 P-gdb.py 的文件并自动读取它。 Dave Malcolm 贡献了一个 python-gdb.py,它添加了许多在调试 Python 本身时有用的命令。例如,py-uppy-down 上下移动一个 Python 堆栈帧,它通常对应于多个 C 堆栈帧。py-print 打印 Python 变量的值,py-bt 打印 Python 堆栈跟踪。(根据 bpo-8032 添加。)

  • 如果您使用 Python 提供的 .gdbinit 文件,则 2.7 版本中的 “pyo” 宏现在在被调试的线程不持有 GIL 时也能正常工作;宏现在在打印之前获取它。(由 Victor Stinner 贡献;bpo-3632。)

  • Py_AddPendingCall() 现在是线程安全的,允许任何工作线程向主 Python 线程提交通知。这对于异步 IO 操作特别有用。(由 Kristján Valur Jónsson 贡献;bpo-4293。)

  • 新函数:PyCode_NewEmpty() 创建一个空代码对象;只需要文件名、函数名称和第一行行号。这对于尝试构造更有用的回溯堆栈的扩展模块很有用。以前,此类扩展需要调用 PyCode_New(),它有更多的参数。(由 Jeffrey Yasskin 添加。)

  • 新函数:PyErr_NewExceptionWithDoc() 创建一个新的异常类,就像现有的 PyErr_NewException() 一样,但它接受一个额外的 char * 参数,其中包含新异常类的文档字符串。(由 Python 错误跟踪器上的 ‘lekma’ 添加;bpo-7033。)

  • 新函数:PyFrame_GetLineNumber() 接收一个帧对象,并返回帧当前正在执行的行号。以前,代码需要获取当前正在执行的字节码指令的索引,然后查找与该地址对应的行号。(由 Jeffrey Yasskin 添加。)

  • 新函数:PyLong_AsLongAndOverflow()PyLong_AsLongLongAndOverflow() 将 Python 长整数近似为 C longlong long。如果该数字太大而无法放入输出类型中,则会设置一个 overflow 标志并返回给调用方。(由 Case Van Horsen 贡献;bpo-7528bpo-7767。)

  • 新函数:由于字符串到浮点数转换的重写,添加了一个新的 PyOS_string_to_double() 函数。旧的 PyOS_ascii_strtod()PyOS_ascii_atof() 函数现在已弃用。

  • 新函数:PySys_SetArgvEx() 设置 sys.argv 的值,并且可以根据 updatepath 参数的值,选择性地更新 sys.path 以包含由 sys.argv[0] 命名的脚本所在的目录。

    添加此函数是为了弥补嵌入 Python 的应用程序中的一个安全漏洞。旧函数 PySys_SetArgv() 总是会更新 sys.path,有时还会添加当前目录。这意味着,如果您在其他人控制的目录中运行嵌入 Python 的应用程序,攻击者可以在该目录中放置一个木马模块(例如,名为 os.py 的文件),您的应用程序随后会导入并运行该模块。

    如果您维护一个嵌入 Python 的 C/C++ 应用程序,请检查您是否正在调用 PySys_SetArgv(),并仔细考虑该应用程序是否应该使用 updatepath 设置为 false 的 PySys_SetArgvEx()

    安全问题报告为 CVE 2008-5983;在 bpo-5753 中讨论,并由 Antoine Pitrou 修复。

  • 新宏:Python 头文件现在定义了以下宏: Py_ISALNUMPy_ISALPHAPy_ISDIGITPy_ISLOWERPy_ISSPACEPy_ISUPPERPy_ISXDIGITPy_TOLOWERPy_TOUPPER。所有这些函数都类似于 C 标准的字符分类宏,但忽略当前的区域设置,因为在某些地方 Python 需要以独立于区域设置的方式分析字符。(由 Eric Smith 添加;bpo-5793。)

  • 已删除的函数: PyEval_CallObject() 现在仅作为宏可用。保留函数版本是为了保持 ABI 链接兼容性,但这在 1997 年就已经实现了;现在肯定可以删除它了。(由 Antoine Pitrou 删除;bpo-8276。)

  • 新格式代码: PyString_FromFormat()PyString_FromFormatV()PyErr_Format() 函数现在接受 %lld%llu 格式代码来显示 C 的 long long 类型。(由 Mark Dickinson 贡献;bpo-7228。)

  • 线程和进程派生之间复杂的交互已更改。以前,os.fork() 创建的子进程可能会失败,因为子进程仅使用一个线程运行创建,即执行 os.fork() 的线程。如果其他线程在执行 fork 时持有锁(例如 Python 的导入锁),则该锁在新的进程中仍将标记为“持有”。但是在子进程中,没有任何东西会释放该锁,因为其他线程没有被复制,并且子进程将无法再执行导入。

    Python 2.7 在执行 os.fork() 之前会获取导入锁,并且还会清理使用 threading 模块创建的任何锁。具有内部锁或自行调用 fork() 的 C 扩展模块将不会受益于此清理。

    (由 Thomas Wouters 修复;bpo-1590864。)

  • Py_Finalize() 函数现在调用内部 threading._shutdown() 函数;这可以防止在解释器关闭时引发某些异常。(由 Adam Olsen 提供的补丁;bpo-1722344。)

  • 当使用 PyMemberDef 结构定义类型的属性时,Python 将不再允许您尝试删除或设置 T_STRING_INPLACE 属性。

  • ctypes 模块定义的全局符号现在以 Py_ctypes 为前缀。(由 Thomas Heller 实现;bpo-3102。)

  • 新的配置选项: --with-system-expat 开关允许构建 pyexpat 模块以使用系统 Expat 库。(由 Arfrever Frehtes Taifersar Arahesis 贡献;bpo-7609。)

  • 新的配置选项: --with-valgrind 选项现在将禁用 pymalloc 分配器,Valgrind 内存错误检测器很难正确分析该分配器。因此,Valgrind 将更好地检测内存泄漏和溢出。(由 James Henstridge 贡献;bpo-2422。)

  • 新的配置选项:现在您可以为 --with-dbmliborder= 提供一个空字符串,以便禁用所有各种 DBM 模块。(由 Arfrever Frehtes Taifersar Arahesis 添加;bpo-6491。)

  • configure 脚本现在检查某些 32 位 Intel 芯片上的浮点舍入错误,并定义一个 X87_DOUBLE_ROUNDING 预处理器定义。当前没有代码使用此定义,但是如果有人希望使用它,可以使用它。(由 Mark Dickinson 添加;bpo-2937。)

    configure 现在还设置一个 LDCXXSHARED Makefile 变量以支持 C++ 链接。(由 Arfrever Frehtes Taifersar Arahesis 贡献;bpo-1222585。)

  • 构建过程现在为 pkg-config 支持创建必要的文件。(由 Clinton Roy 贡献;bpo-3585。)

  • 构建过程现在支持 Subversion 1.7。(由 Arfrever Frehtes Taifersar Arahesis 贡献;bpo-6094。)

胶囊

Python 3.1 添加了一个新的 C 数据类型 PyCapsule,用于为扩展模块提供 C API。胶囊本质上是 C void * 指针的持有者,并作为模块属性提供;例如,socket 模块的 API 以 socket.CAPI 的形式公开,而 unicodedata 公开 ucnhash_CAPI。其他扩展可以导入该模块,访问其字典以获取胶囊对象,然后获取 void * 指针,该指针通常指向指向该模块的各种 API 函数的指针数组。

已经存在用于此目的的数据类型 PyCObject,但是它不提供类型安全。用纯 Python 编写的恶意代码可能会导致分段错误,方法是从模块 A 中获取 PyCObject,并以某种方式将其替换为模块 B 中的 PyCObject。胶囊知道自己的名称,并且获取指针需要提供名称

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() 以处理胶囊,从而保持与 PyCObject 接口的编译时兼容性。使用 PyCObject_AsVoidPtr() 将发出一个 PendingDeprecationWarning,默认情况下它是静默的。

由 Larry Hastings 在 Python 3.1 中实现并向后移植到 2.7;在 bpo-5630 中讨论。

特定于端口的更改:Windows

特定于端口的更改:Mac OS X

  • 为了在系统安装和同一版本的用户安装副本之间共享添加的软件包,路径 /Library/Python/2.7/site-packages 现在被附加到 sys.path。(由 Ronald Oussoren 更改;bpo-4865。)

    在 2.7.13 版本中更改:从 2.7.13 版本开始,此更改已被删除。对于用户安装的 Python,如来自 python.org 安装程序的 Python,/Library/Python/2.7/site-packages,即 Apple 提供的系统 Python 2.7 使用的 site-packages 目录,不再附加到 sys.path。从 macOS 10.12 开始,Apple 更改了系统 site-packages 目录的配置方式,这可能导致安装 pip 组件(如 setuptools)失败。为系统 Python 安装的软件包将不再与用户安装的 Python 共享。(bpo-28440

特定于端口的更改:FreeBSD

  • FreeBSD 7.1 的 SO_SETFIB 常量,与 socket() 方法 getsockopt()/setsockopt() 一起使用以选择备用路由表,现在可以在 socket 模块中使用。(由 Kyle VanderBeek 添加;bpo-8235。)

其他更改和修复

  • 两个基准测试脚本 iobenchccbench 已添加到 Tools 目录。iobench 测量 open() 返回的内置文件 I/O 对象在执行各种操作时的速度,而 ccbench 是一个并发基准测试,它尝试测量使用不同数量的线程执行多个任务时的计算吞吐量、线程切换延迟和 I/O 处理带宽。

  • Tools/i18n/msgfmt.py 脚本现在可以理解 .po 文件中的复数形式。(由 Martin von Löwis 修复;bpo-5464。)

  • 当从带有现有 .py 对应文件的 .pyc.pyo 文件导入模块时,当原始文件名过时时,会覆盖结果代码对象的 co_filename 属性。如果文件已重命名、移动或通过不同的路径访问,则可能发生这种情况。(由 Ziga Seilnacht 和 Jean-Paul Calderone 修复;bpo-1180193。)

  • regrtest.py 脚本现在采用 --randseed= 开关,该开关接受一个整数,该整数将用作 -r 选项的随机种子,该选项以随机顺序执行测试。-r 选项还会报告使用的种子(由 Collin Winter 添加。)

  • regrtest.py 的另一个开关是 -j,它接受一个整数,指定多少个测试并行运行。这允许在多核机器上减少总运行时间。此选项与多个其他选项兼容,包括已知会产生长时间运行的 -R 开关。(由 Antoine Pitrou 添加,bpo-6152。)它还可以与新的 -F 开关一起使用,该开关循环运行选定的测试,直到它们失败。(由 Antoine Pitrou 添加;bpo-7312。)

  • 当作为脚本执行时,py_compile.py 模块现在接受 '-' 作为参数,它将从标准输入读取要编译的文件名列表。(由 Piotr Ożarowski 贡献;bpo-8233。)

移植到 Python 2.7

本节列出了先前描述的更改和其他错误修复,这些更改可能需要更改您的代码

  • range() 函数更一致地处理其参数;它现在将对提供给它的非浮点、非整数参数调用 __int__()。(由 Alexander Belopolsky 修复;bpo-1533。)

  • 字符串 format() 方法将浮点数和复数的默认精度从 6 位小数更改为 12 位小数,这与 str() 使用的精度匹配。(由 Eric Smith 更改;bpo-5920。)

  • 由于对 with 语句的优化,特殊方法 __enter__()__exit__() 必须属于对象的类型,而不能直接附加到对象的实例。这会影响新式类(从 object 派生)和 C 扩展类型。(bpo-6101。)

  • 由于 Python 2.6 中的一个错误,__exit__() 方法的 exc_value 参数通常是异常的字符串表示形式,而不是实例。这个问题在 2.7 中得到了修复,因此 exc_value 将按预期成为一个实例。(由 Florent Xicluna 修复;bpo-7853。)

  • 当使用 __slots__ 设置了受限的属性集时,删除未设置的属性不会像预期那样引发 AttributeError。由 Benjamin Peterson 修复;bpo-7604。)

在标准库中

  • datetime 实例进行操作,如果结果年份超出支持的范围,以前不总是会引发 OverflowError 异常。现在对此类错误进行了更仔细的检查,并且会引发该异常。(由 Mark Leander 报告,Anand B. Pillai 和 Alexander Belopolsky 提供了补丁;bpo-7150。)

  • 当将 Decimal 实例与字符串的 format() 方法一起使用时,默认对齐方式以前是左对齐。现在已更改为右对齐,这可能会更改程序的输出。(由 Mark Dickinson 更改;bpo-6857。)

    涉及信号 NaN 值(或 sNAN)的比较现在会发出 InvalidOperation 信号,而不是根据比较运算符静默地返回 true 或 false 值。现在,安静的 NaN 值(或 NaN)是可哈希的。(由 Mark Dickinson 修复;bpo-7279。)

  • xml.etree.ElementTree 库在输出 XML 处理指令(看起来像 <?xml-stylesheet href="#style1"?>)或注释(看起来像 <!-- comment -->)时,不再转义 & 符号和尖括号。(Neil Muller 提供了补丁;bpo-2746。)

  • StringIO 对象的 readline() 方法现在在请求负长度时,会像其他类文件对象一样不执行任何操作。(bpo-7348)。

  • 现在,syslog 模块将使用 sys.argv[0] 的值作为标识符,而不是之前的默认值 'python'。(由 Sean Reifschneider 更改;bpo-8451。)

  • tarfile 模块的默认错误处理已更改,不再抑制致命错误。之前的默认错误级别为 0,这意味着错误只会导致将消息写入调试日志,但由于默认情况下未激活调试日志,因此这些错误会被忽略。现在的默认错误级别为 1,如果发生错误,则会引发异常。(由 Lars Gustäbel 更改;bpo-7357。)

  • urlparse 模块的 urlsplit() 现在以符合 RFC 3986 的方式处理未知的 URL 方案:如果 URL 的形式为 "<something>://...",则 :// 之前的文本将被视为方案,即使它是一个模块不知道的虚构方案。此更改可能会破坏绕开旧行为的代码。例如,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 扩展

对于嵌入 Python 的应用程序

  • 添加了 PySys_SetArgvEx() 函数,允许应用程序在使用现有的 PySys_SetArgv() 函数时关闭安全漏洞。请检查您是否正在调用 PySys_SetArgv(),并仔细考虑应用程序是否应该使用 updatepath 设置为 false 的 PySys_SetArgvEx()

添加到 Python 2.7 维护版本中的新功能

当情况确实需要时,可能会在 Python 2.7 维护版本中添加新功能。任何此类添加都必须通过 Python 增强提案流程,并提出令人信服的理由,说明为什么不能仅通过将新功能添加到 Python 3 中或将其发布在 Python 包索引中来充分解决这些问题。

除了下面列出的特定提案外,还有一个通用豁免,允许在任何 Python 2.7 维护版本中添加新的 -3 警告。

调试模式的两个新环境变量

在调试模式下,默认情况下不写入 [xxx refs] 统计信息,现在还必须设置 PYTHONSHOWREFCOUNT 环境变量。(由 Victor Stinner 提供;bpo-31733。)

当使用定义的 COUNT_ALLOC 编译 Python 时,默认情况下不再转储分配计数:现在还必须设置 PYTHONSHOWALLOCCOUNT 环境变量。此外,分配计数现在被转储到 stderr,而不是 stdout。(由 Victor Stinner 提供;bpo-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 中添加的相关功能

  • 从 Python 3 反向移植了 hmac.compare_digest(),以便为 Python 2 应用程序提供抗时序攻击的比较操作。(由 Alex Gaynor 提供;bpo-21306。)

  • 在 python.org 上发布的官方 Windows 安装程序中升级了 OpenSSL 1.0.1g。(由 Zachary Ware 提供;bpo-21462。)

PEP 466 在 Python 2.7.8 中添加的相关功能

  • 从 Python 3 反向移植了 hashlib.pbkdf2_hmac(),以便为 Python 2 应用程序广泛提供适用于安全密码存储的哈希算法。(由 Alex Gaynor 提供;bpo-21304。)

  • 为在 python.org 上发布的官方 Windows 安装程序升级了 OpenSSL 1.0.1h。(由 Zachary Ware 在 bpo-21671 中为 CVE 2014-0224 提供。)

PEP 466 在 Python 2.7.9 中添加的相关功能

  • Python 3.4 的 ssl 模块的大部分功能已被向后移植。这意味着 ssl 现在支持服务器名称指示(Server Name Indication)、TLS1.x 设置、访问平台证书存储、SSLContext 类以及其他功能。(由 Alex Gaynor 和 David Reid 贡献;bpo-21308。)

    有关具体详细信息,请参阅模块文档中的“添加版本:2.7.9”注释。

  • os.urandom() 已被更改为缓存指向 /dev/urandom 的文件描述符,而不是在每次调用时重新打开 /dev/urandom。(由 Alex Gaynor 贡献;bpo-21305。)

  • hashlib.algorithms_guaranteedhashlib.algorithms_available 从 Python 3 向后移植,以方便 Python 2 应用程序选择最强的可用哈希算法。(由 Alex Gaynor 在 bpo-21307 中贡献)

PEP 477:将 ensurepip (PEP 453) 向后移植到 Python 2.7

PEP 477 批准在 Python 2.7 维护版本中包含 PEP 453 ensurepip 模块以及由此启用的改进的文档,首次出现在 Python 2.7.9 版本中。

默认引导 pip

新的 ensurepip 模块(在 PEP 453 中定义)提供了一个标准的跨平台机制,用于将 pip 安装程序引导到 Python 安装中。Python 2.7.9 中包含的 pip 版本是 pip 1.5.6,未来的 2.7.x 维护版本会将捆绑版本更新为创建候选版本时可用的最新 pip 版本。

默认情况下,命令 pippipXpipX.Y 将安装在所有平台上(其中 X.Y 代表 Python 安装的版本),同时还会安装 pip Python 包及其依赖项。

对于 CPython 在 POSIX 系统上的源代码构建make installmake altinstall 命令默认情况下不引导 pip。可以通过配置选项控制此行为,并通过 Makefile 选项覆盖此行为。

在 Windows 和 Mac OS X 上,CPython 安装程序现在默认安装 pip 以及 CPython 本身(用户可以选择在安装过程中不安装它)。Windows 用户需要选择加入自动 PATH 修改,以便默认情况下可以从命令行使用 pip,否则仍然可以通过 Windows 的 Python 启动器作为 py -m pip 访问它。

正如 PEP 中讨论的那样,平台打包者可以选择默认不安装这些命令,只要在调用时,它们提供关于如何在平台上安装它们的清晰简单的指导(通常使用系统包管理器)。

文档更改

作为此更改的一部分,文档的 安装 Python 模块分发 Python 模块 部分已被完全重新设计为简短的入门和常见问题解答文档。大多数打包文档现在已移至 Python Packaging Authority 维护的 Python 打包用户指南 和各个项目的文档中。

但是,由于此迁移目前仍未完成,这些指南的旧版本仍然作为 使用 setuptools 构建 C 和 C++ 扩展使用 setuptools 构建 C 和 C++ 扩展 提供。

另请参阅

PEP 453 – Python 安装中 pip 的显式引导

由 Donald Stufft 和 Nick Coghlan 编写的 PEP,由 Donald Stufft、Nick Coghlan、Martin von Löwis 和 Ned Deily 实现。

PEP 476:默认情况下为 stdlib http 客户端启用证书验证

PEP 476 更新了 httplib 以及使用它的模块,例如 urllib2xmlrpclib,现在默认情况下会验证服务器是否出示了由平台信任存储中的证书颁发机构签名的证书,并且其主机名与请求的主机名匹配,从而显著提高了许多应用程序的安全性。此更改是在 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 构建目标

为了简化交叉编译,并确保 CPython 可以可靠地编译而无需现有版本的 Python,基于 autotools 的构建系统不再尝试基于文件修改时间隐式重新编译生成的文件。

相反,添加了一个新的 make regen-all 命令,以便在需要时(例如,在基于预生成版本已经构建了初始版本的 Python 后)强制重新生成这些文件。

还定义了更具选择性的重新生成目标 - 有关详细信息,请参见 Makefile.pre.in

(由 Victor Stinner 在 bpo-23404 中贡献。)

在 2.7.14 版本中添加。

删除 make touch 构建目标

以前用于通过更新修改时间来请求隐式重新生成生成文件的 make touch 构建目标已删除。

它已被新的 make regen-all 目标取代。

(由 Victor Stinner 在 bpo-23404 中贡献。)

在 2.7.14 版本中更改。

致谢

作者感谢以下人士对本文的各个草案提供了建议、更正和帮助:Nick Coghlan、Philip Jenvey、Ryan Lovett、R. David Murray、Hugh Secker-Walker。