Python 2.6 新特性

作者:

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

本文介绍了 Python 2.6 的新特性,该版本于 2008 年 10 月 1 日发布。发布计划在 PEP 361 中描述。

Python 2.6 的主要主题是为迁移到 Python 3.0(该语言的重大重新设计)做准备。在可能的情况下,Python 2.6 会合并来自 3.0 的新特性和语法,同时通过不删除旧特性或语法来保持与现有代码的兼容性。当无法做到这一点时,Python 2.6 会尽力而为,在 future_builtins 模块中添加兼容性函数,并添加 -3 开关来警告 3.0 中将不再支持的用法。

一些重要的新包已添加到标准库中,例如 multiprocessingjson 模块,但没有太多与 Python 3.0 无关的新特性。

Python 2.6 还在整个源代码中进行了许多改进和错误修复。搜索变更日志发现,在 Python 2.5 和 2.6 之间应用了 259 个补丁并修复了 612 个错误。这两个数字都可能被低估了。

本文不试图提供新特性的完整规范,而是提供一个方便的概述。有关完整详细信息,您应该参考 Python 2.6 的文档。如果您想了解设计和实现的原理,请参考特定新特性的 PEP。在可能的情况下,“Python 新特性”会链接到每个变更的错误/补丁项。

Python 3.0

Python 版本 2.6 和 3.0 的开发周期是同步的,两个版本的 alpha 和 beta 版本都在同一天发布。3.0 的开发影响了 2.6 中的许多特性。

Python 3.0 是对 Python 的重大重新设计,它打破了与 2.x 系列的兼容性。这意味着现有的 Python 代码需要进行一些转换才能在 Python 3.0 上运行。但是,并非 3.0 中的所有更改都必然会破坏兼容性。在新特性不会导致现有代码中断的情况下,它们已被反向移植到 2.6 中,并在本文档的适当位置进行了描述。一些 3.0 派生的特性是:

  • 用于将对象转换为复数的 __complex__() 方法。

  • 用于捕获异常的替代语法:except TypeError as exc

  • 添加 functools.reduce() 作为内置 reduce() 函数的同义词。

Python 3.0 添加了几个新的内置函数,并更改了一些现有内置函数的语义。像 bin() 这样在 3.0 中是新的函数已被简单地添加到 Python 2.6 中,但现有的内置函数没有被更改;相反,future_builtins 模块具有具有新 3.0 语义的版本。为与 3.0 兼容而编写的代码可以根据需要执行 from future_builtins import hex, map

一个新的命令行开关 -3,启用有关 Python 3.0 中将删除的功能的警告。您可以使用此开关运行代码,以查看将代码移植到 3.0 需要多少工作。此开关的值可作为布尔变量 sys.py3kwarning 提供给 Python 代码,并作为 Py_Py3kWarningFlag 提供给 C 扩展代码。

另请参阅

3xxx 系列的 PEP,其中包含 Python 3.0 的提案。PEP 3000 描述了 Python 3.0 的开发过程。从 PEP 3100 开始,该文档描述了 Python 3.0 的总体目标,然后探索提出特定功能的高编号 PEP。

开发流程的变更

在开发 2.6 时,Python 开发过程经历了两个重大变化:我们从 SourceForge 的问题跟踪器切换到定制的 Roundup 安装,文档从 LaTeX 转换为 reStructuredText。

新的问题跟踪器:Roundup

长期以来,Python 开发人员对 SourceForge 的错误跟踪器越来越感到恼火。SourceForge 的托管解决方案不允许太多自定义;例如,无法自定义问题的生命周期。

因此,Python 软件基金会的基础设施委员会发布了问题跟踪器的征集,要求志愿者设置不同的产品并从 SourceForge 导入一些错误和补丁。检查了四个不同的跟踪器:JiraLaunchpadRoundupTrac。委员会最终确定 Jira 和 Roundup 为两个候选者。Jira 是一款商业产品,为自由软件项目提供免费托管实例;Roundup 是一个开源项目,需要志愿者来管理它和一个服务器来托管它。

在发布志愿者征集后,在 https://bugs.python.org 上设置了一个新的 Roundup 安装。一个 Roundup 安装可以托管多个跟踪器,并且该服务器现在还托管 Jython 和 Python 网站的问题跟踪器。将来它肯定会找到其他用途。在可能的情况下,此版本的“Python 新特性”会链接到每个变更的错误/补丁项。

Python 错误跟踪器的托管由南非斯泰伦博斯的 Upfront Systems 慷慨提供。Martin von Löwis 花费了大量精力从 SourceForge 导入现有的错误和补丁;他用于此导入操作的脚本位于 https://svn.python.org/view/tracker/importer/,可能对希望从 SourceForge 迁移到 Roundup 的其他项目有用。

另请参阅

https://bugs.python.org

Python 错误跟踪器。

https://bugs.jython.org:

Jython 错误跟踪器。

https://roundup.sourceforge.io/

Roundup 下载和文档。

https://svn.python.org/view/tracker/importer/

Martin von Löwis 的转换脚本。

新的文档格式:使用 Sphinx 的 reStructuredText

自 1989 年左右项目启动以来,Python 文档一直使用 LaTeX 编写。在 20 世纪 80 年代和 90 年代初期,大多数文档都是打印出来以便日后学习,而不是在线查看。LaTeX 被广泛使用,因为它提供了美观的打印输出,同时在掌握了标记的基本规则后编写起来也很简单。

如今,LaTeX 仍然用于编写用于打印的出版物,但编程工具的格局已经发生了变化。我们不再打印大量的文档;相反,我们在线浏览它们,而 HTML 已成为最重要的支持格式。不幸的是,将 LaTeX 转换为 HTML 相当复杂,长期担任 Python 文档编辑的 Fred L. Drake Jr. 花费了大量时间来维护转换过程。偶尔有人会建议将文档转换为 SGML,后来又建议转换为 XML,但执行良好的转换是一项重大任务,没有人投入必要的时间来完成这项工作。

在 2.6 开发周期中,Georg Brandl 花费了大量精力来构建新的工具链来处理文档。由此产生的软件包名为 Sphinx,可从 https://sphinx-doc.cn/ 获取。

Sphinx 专注于 HTML 输出,生成样式美观且现代的 HTML;通过转换为 LaTeX 仍然支持打印输出。输入格式是 reStructuredText,这是一种支持自定义扩展和指令的标记语法,在 Python 社区中很常用。

Sphinx 是一个独立的软件包,可用于编写,并且其他近二十几个项目(在 Sphinx 网站上列出)已采用 Sphinx 作为其文档工具。

另请参阅

编写 Python 文档

描述如何为 Python 文档编写内容。

Sphinx

Sphinx 工具链的文档和代码。

Docutils

底层 reStructuredText 解析器和工具集。

PEP 343:‘with’ 语句

之前的版本 Python 2.5 添加了 ‘with’ 语句作为可选功能,通过 from __future__ import with_statement 指令启用。在 2.6 中,该语句不再需要特别启用;这意味着 with 现在始终是一个关键字。本节的其余部分是来自“Python 2.5 中的新增功能”文档中相应部分的副本;如果您熟悉 Python 2.5 中的 ‘with’ 语句,则可以跳过本节。

with’ 语句简化了以前会使用 try...finally 代码块来确保执行清理代码的代码。在本节中,我将讨论该语句的常用方式。在下一节中,我将检查实现细节,并展示如何编写与此语句一起使用的对象。

with’ 语句是一个控制流结构,其基本结构为

with expression [as variable]:
    with-block

计算表达式的值,它应该产生一个支持上下文管理协议的对象(即,具有 __enter__()__exit__() 方法)。

在执行 *with-block* 之前调用对象的 __enter__(),因此可以运行设置代码。如果给出,它还可能返回一个绑定到名称 *variable* 的值。(请注意,*variable* 不是赋值为 *expression* 的结果。)

在 *with-block* 执行完成后,将调用对象的 __exit__() 方法,即使该代码块引发了异常,因此可以运行清理代码。

一些标准的 Python 对象现在支持上下文管理协议,并且可以与 ‘with’ 语句一起使用。文件对象就是一个例子

with open('/etc/passwd', 'r') as f:
    for line in f:
        print line
        ... more processing code ...

在此语句执行后,*f* 中的文件对象将自动关闭,即使 for 循环在代码块执行过程中引发了异常。

注意

在这种情况下,*f* 是由 open() 创建的同一个对象,因为 __enter__() 返回 *self*。

threading 模块的锁和条件变量也支持 ‘with’ 语句

lock = threading.Lock()
with lock:
    # Critical section of code
    ...

在执行代码块之前获取锁,并在代码块完成后始终释放锁。

decimal 模块中的 localcontext() 函数可以轻松保存和还原当前的十进制上下文,该上下文封装了计算所需的精度和舍入特性

from decimal import Decimal, Context, localcontext

# Displays with default precision of 28 digits
v = Decimal('578')
print v.sqrt()

with localcontext(Context(prec=16)):
    # All code in this block uses a precision of 16 digits.
    # The original context is restored on exiting the block.
    print v.sqrt()

编写上下文管理器

在幕后,‘with’ 语句相当复杂。大多数人只会在现有对象中使用 ‘with’,而无需了解这些细节,因此如果您愿意,可以跳过本节的其余部分。新对象的作者需要了解底层实现的细节,并且应该继续阅读。

上下文管理协议的高级解释是

  • 计算表达式的值,它应该产生一个名为“上下文管理器”的对象。上下文管理器必须具有 __enter__()__exit__() 方法。

  • 调用上下文管理器的 __enter__() 方法。返回的值分配给 *VAR*。如果没有 as VAR 子句,则该值将被直接丢弃。

  • 执行 *BLOCK* 中的代码。

  • 如果 *BLOCK* 引发异常,则使用三个参数调用上下文管理器的 __exit__() 方法,即异常详细信息(type、value、traceback,与 sys.exc_info() 返回的值相同,如果没有发生异常,则也可以为 None)。该方法的返回值控制是否重新引发异常:任何虚假值都会重新引发异常,而 True 将导致抑制异常。您很少会想要抑制异常,因为如果这样做,则包含 ‘with’ 语句的代码的作者将永远不会意识到任何问题。

  • 如果 *BLOCK* 没有引发异常,则仍然会调用 __exit__() 方法,但 *type*、*value* 和 *traceback* 都为 None

让我们考虑一个例子。我不会提供详细的代码,而只会草拟支持事务的数据库所需的方法。

(对于不熟悉数据库术语的人:对数据库的一组更改被分组到一个事务中。事务可以提交,这意味着所有更改都写入数据库,或者回滚,这意味着所有更改都被丢弃,并且数据库保持不变。有关更多信息,请参阅任何数据库教科书。)

假设有一个表示数据库连接的对象。我们的目标是让用户编写如下代码

db_connection = DatabaseConnection()
with db_connection as cursor:
    cursor.execute('insert into ...')
    cursor.execute('delete from ...')
    # ... more operations ...

如果代码块中的代码完美运行,则应提交事务,如果出现异常,则应回滚事务。这是我假设的 DatabaseConnection 的基本接口

class DatabaseConnection:
    # Database interface
    def cursor(self):
        "Returns a cursor object and starts a new transaction"
    def commit(self):
        "Commits current transaction"
    def rollback(self):
        "Rolls back current transaction"

__enter__() 方法非常简单,只需要启动一个新的事务。对于这个应用程序,生成的游标对象将是一个有用的结果,因此该方法将返回它。然后,用户可以在他们的 ‘with’ 语句中添加 as cursor 来将游标绑定到一个变量名。

class DatabaseConnection:
    ...
    def __enter__(self):
        # Code to start a new transaction
        cursor = self.cursor()
        return cursor

__exit__() 方法是最复杂的,因为它需要完成大部分工作。该方法必须检查是否发生了异常。如果没有异常,则提交事务。如果存在异常,则回滚事务。

在下面的代码中,执行将直接从函数末尾退出,返回默认值 NoneNone 为假,因此异常将自动重新抛出。如果需要,你可以更明确地在标记的位置添加一个 return 语句。

class DatabaseConnection:
    ...
    def __exit__(self, type, value, tb):
        if tb is None:
            # No exception, so commit
            self.commit()
        else:
            # Exception occurred, so rollback.
            self.rollback()
            # return False

contextlib 模块

contextlib 模块提供了一些函数和一个装饰器,当编写用于 ‘with’ 语句的对象时,这些函数和装饰器非常有用。

该装饰器名为 contextmanager(),它允许你编写单个生成器函数,而不是定义一个新的类。生成器应该恰好 yield 一个值。 yield 之前的所有代码都将作为 __enter__() 方法执行,而 yield 的值将是该方法的返回值,它将绑定到 ‘with’ 语句的 as 子句中的变量(如果有)。 yield 之后的所有代码都将在 __exit__() 方法中执行。块中引发的任何异常都将由 yield 语句引发。

使用此装饰器,我们可以将上一节中的数据库示例编写为:

from contextlib import contextmanager

@contextmanager
def db_transaction(connection):
    cursor = connection.cursor()
    try:
        yield cursor
    except:
        connection.rollback()
        raise
    else:
        connection.commit()

db = DatabaseConnection()
with db_transaction(db) as cursor:
    ...

contextlib 模块还有一个 nested(mgr1, mgr2, ...) 函数,它组合了多个上下文管理器,因此你不需要编写嵌套的 ‘with’ 语句。在此示例中,单个 ‘with’ 语句既启动数据库事务又获取线程锁

lock = threading.Lock()
with nested (db_transaction(db), lock) as (cursor, locked):
    ...

最后,closing() 函数返回其参数,以便可以将其绑定到变量,并在块的末尾调用该参数的 .close() 方法。

import urllib, sys
from contextlib import closing

with closing(urllib.urlopen('http://www.yahoo.com')) as f:
    for line in f:
        sys.stdout.write(line)

另请参阅

PEP 343 - “with” 语句

由 Guido van Rossum 和 Nick Coghlan 编写的 PEP;由 Mike Bland、Guido van Rossum 和 Neal Norwitz 实现。该 PEP 显示了为 ‘with’ 语句生成的代码,这有助于了解该语句的工作原理。

contextlib 模块的文档。

PEP 366:从主模块进行显式相对导入

Python 的 -m 开关允许将模块作为脚本运行。当你运行位于包内的模块时,相对导入无法正常工作。

Python 2.6 的修复程序添加了 module.__package__ 属性。当此属性存在时,相对导入将相对于此属性的值,而不是 __name__ 属性。

然后,PEP 302 样式的导入器可以根据需要设置 __package__runpy 模块实现了 -m 开关,现在可以执行此操作,因此相对导入现在可以在从包内部运行的脚本中正常工作。

PEP 370:每个用户的 site-packages 目录

当你运行 Python 时,模块搜索路径 sys.path 通常包含一个路径以 "site-packages" 结尾的目录。此目录旨在保存本地安装的包,这些包可供使用机器或特定站点安装的所有用户使用。

Python 2.6 引入了特定于用户的站点目录的约定。该目录因平台而异

  • Unix 和 Mac OS X:~/.local/

  • Windows:%APPDATA%/Python

在此目录中,将有特定于版本的子目录,例如 Unix/Mac OS 上的 lib/python2.6/site-packages 和 Windows 上的 Python26/site-packages

如果你不喜欢默认目录,可以通过环境变量覆盖它。PYTHONUSERBASE 设置用于支持此功能的所有 Python 版本的根目录。在 Windows 上,可以通过设置 APPDATA 环境变量来更改特定于应用程序的数据目录。你还可以修改 Python 安装的 site.py 文件。

可以通过使用 -s 选项运行 Python 或设置 PYTHONNOUSERSITE 环境变量来完全禁用此功能。

另请参阅

PEP 370 - 每个用户的 site-packages 目录

由 Christian Heimes 编写和实现的 PEP。

PEP 371:multiprocessing

新的 multiprocessing 包允许 Python 程序创建新进程,这些进程将执行计算并将结果返回给父进程。父进程和子进程可以使用队列和管道进行通信,使用锁和信号量同步其操作,并且可以共享简单的数据数组。

multiprocessing 模块最初是 threading 模块的精确仿真,使用进程而不是线程。该目标在 Python 2.6 的开发过程中被放弃,但该模块的总体方法仍然相似。基本类是 Process,它传递一个可调用对象和一组参数。start() 方法在子进程中设置可调用对象运行,之后你可以调用 is_alive() 方法来检查子进程是否仍在运行,并调用 join() 方法来等待进程退出。

这是一个简单的示例,其中子进程将计算阶乘。执行计算的函数编写得很奇怪,当输入参数是 4 的倍数时,它会花费更长的时间。

import time
from multiprocessing import Process, Queue


def factorial(queue, N):
    "Compute a factorial."
    # If N is a multiple of 4, this function will take much longer.
    if (N % 4) == 0:
        time.sleep(.05 * N/4)

    # Calculate the result
    fact = 1L
    for i in range(1, N+1):
        fact = fact * i

    # Put the result on the queue
    queue.put(fact)

if __name__ == '__main__':
    queue = Queue()

    N = 5

    p = Process(target=factorial, args=(queue, N))
    p.start()
    p.join()

    result = queue.get()
    print 'Factorial', N, '=', result

Queue 用于传递阶乘的结果。Queue 对象存储在全局变量中。子进程将在创建子进程时使用该变量的值;因为它是 Queue,父进程和子进程可以使用该对象进行通信。(如果父进程更改了全局变量的值,则子进程的值不会受到影响,反之亦然。)

另外两个类,PoolManager,提供了更高级别的接口。Pool 将创建固定数量的工作进程,然后可以通过调用 apply()apply_async() 添加单个请求,以及通过调用 map()map_async() 添加多个请求,将请求分发给这些工作进程。以下代码使用 Pool 将请求分散到 5 个工作进程中,并检索结果列表

from multiprocessing import Pool

def factorial(N, dictionary):
    "Compute a factorial."
    ...
p = Pool(5)
result = p.map(factorial, range(1, 1000, 10))
for v in result:
    print v

这将产生以下输出

1
39916800
51090942171709440000
8222838654177922817725562880000000
33452526613163807108170062053440751665152000000000
...

另一个高级接口 Manager 类,会创建一个单独的服务器进程,该进程可以保存 Python 数据结构的主副本。然后,其他进程可以使用代理对象访问和修改这些数据结构。以下示例通过调用 dict() 方法创建一个共享字典;然后,工作进程将值插入到字典中。(不会自动为您执行锁定,这在本示例中无关紧要。Manager 的方法还包括 Lock()RLock()Semaphore() 来创建共享锁。)

import time
from multiprocessing import Pool, Manager

def factorial(N, dictionary):
    "Compute a factorial."
    # Calculate the result
    fact = 1L
    for i in range(1, N+1):
        fact = fact * i

    # Store result in dictionary
    dictionary[N] = fact

if __name__ == '__main__':
    p = Pool(5)
    mgr = Manager()
    d = mgr.dict()         # Create shared dictionary

    # Run tasks using the pool
    for N in range(1, 1000, 10):
        p.apply_async(factorial, (N, d))

    # Mark pool as closed -- no more tasks can be added.
    p.close()

    # Wait for tasks to exit
    p.join()

    # Output results
    for k, v in sorted(d.items()):
        print k, v

这将产生以下输出

1 1
11 39916800
21 51090942171709440000
31 8222838654177922817725562880000000
41 33452526613163807108170062053440751665152000000000
51 15511187532873822802242430164693032110632597200169861120000...

另请参阅

multiprocessing 模块的文档。

PEP 371 - 添加 multiprocessing 包

由 Jesse Noller 和 Richard Oudkerk 编写的 PEP;由 Richard Oudkerk 和 Jesse Noller 实现。

PEP 3101:高级字符串格式化

在 Python 3.0 中,% 运算符由更强大的字符串格式化方法 format() 补充。str.format() 方法的支持已向后移植到 Python 2.6。

在 2.6 中,8 位和 Unicode 字符串都有一个 .format() 方法,该方法将字符串视为模板并采用要格式化的参数。格式化模板使用花括号 ({, }) 作为特殊字符

>>> # Substitute positional argument 0 into the string.
>>> "User ID: {0}".format("root")
'User ID: root'
>>> # Use the named keyword arguments
>>> "User ID: {uid}   Last seen: {last_login}".format(
...    uid="root",
...    last_login = "5 Mar 2008 07:20")
'User ID: root   Last seen: 5 Mar 2008 07:20'

可以通过将花括号加倍来转义它们

>>> "Empty dict: {{}}".format()
"Empty dict: {}"

字段名称可以是表示位置参数的整数,例如 {0}{1} 等,或者是关键字参数的名称。您还可以提供读取属性或访问字典键的复合字段名称

>>> import sys
>>> print 'Platform: {0.platform}\nPython version: {0.version}'.format(sys)
Platform: darwin
Python version: 2.6a1+ (trunk:61261M, Mar  5 2008, 20:29:41)
[GCC 4.0.1 (Apple Computer, Inc. build 5367)]'

>>> import mimetypes
>>> 'Content-type: {0[.mp4]}'.format(mimetypes.types_map)
'Content-type: video/mp4'

请注意,当使用字典样式表示法(例如 [.mp4])时,无需在字符串周围添加任何引号;它将使用 .mp4 作为键来查找值。以数字开头的字符串将被转换为整数。您不能在格式字符串中编写更复杂的表达式。

到目前为止,我们已经展示了如何指定将哪个字段替换到结果字符串中。还可以通过添加冒号后跟格式说明符来控制使用的精确格式。例如

>>> # Field 0: left justify, pad to 15 characters
>>> # Field 1: right justify, pad to 6 characters
>>> fmt = '{0:15} ${1:>6}'
>>> fmt.format('Registration', 35)
'Registration    $    35'
>>> fmt.format('Tutorial', 50)
'Tutorial        $    50'
>>> fmt.format('Banquet', 125)
'Banquet         $   125'

格式说明符可以通过嵌套引用其他字段

>>> fmt = '{0:{1}}'
>>> width = 15
>>> fmt.format('Invoice #1234', width)
'Invoice #1234  '
>>> width = 35
>>> fmt.format('Invoice #1234', width)
'Invoice #1234                      '

可以指定字段在所需宽度内的对齐方式

字符

效果

< (默认)

左对齐

>

右对齐

^

居中

=

(仅用于数字类型)在符号后填充。

格式说明符还可以包括表示类型,该类型控制如何格式化值。例如,浮点数可以格式化为普通数字或指数表示法

>>> '{0:g}'.format(3.75)
'3.75'
>>> '{0:e}'.format(3.75)
'3.750000e+00'

有多种表示类型可用。有关 完整列表,请参阅 2.6 文档;这是一个示例

b

二进制。以 2 为底输出数字。

c

字符。在打印之前将整数转换为相应的 Unicode 字符。

d

十进制整数。以 10 为底输出数字。

o

八进制格式。以 8 为底输出数字。

x

十六进制格式。以 16 为底输出数字,对于 9 以上的数字使用小写字母。

e

指数表示法。使用字母“e”来指示指数,以科学记数法打印数字。

g

通用格式。这会将数字打印为定点数字,除非该数字太大,在这种情况下它会切换到“e”指数表示法。

n

数字。这与“g”(对于浮点数)或“d”(对于整数)相同,但它使用当前的语言环境设置来插入适当的数字分隔符。

%

百分比。将数字乘以 100 并以固定 ('f') 格式显示,后跟百分号。

类和类型可以定义一个 __format__() 方法来控制它们的格式化方式。它接收一个参数,即格式说明符

def __format__(self, format_spec):
    if isinstance(format_spec, unicode):
        return unicode(str(self))
    else:
        return str(self)

还有一个 format() 内置函数,可以格式化单个值。它使用提供的说明符调用类型的 __format__() 方法

>>> format(75.6564, '.2f')
'75.66'

另请参阅

格式字符串语法

格式字段的参考文档。

PEP 3101 - 高级字符串格式化

由 Talin 编写的 PEP。由 Eric Smith 实现。

PEP 3105:print 作为函数

print 语句在 Python 3.0 中变为 print() 函数。将 print() 变为函数,可以通过执行 def print(...) 或从其他地方导入新函数来替换该函数。

Python 2.6 有一个 __future__ 导入,该导入会删除作为语言语法的 print,让您可以改为使用函数形式。例如

>>> from __future__ import print_function
>>> print('# of entries', len(dictionary), file=sys.stderr)

新函数的签名是

def print(*args, sep=' ', end='\n', file=None)

参数是

  • args: 位置参数,其值将被打印出来。

  • sep: 分隔符,将在参数之间打印。

  • end: 结尾文本,将在所有参数输出后打印。

  • file: 输出将发送到的文件对象。

另请参阅

PEP 3105 - 将 print 作为函数

由 Georg Brandl 编写的 PEP。

PEP 3110:异常处理更改

Python 程序员偶尔会犯的一个错误是编写以下代码

try:
    ...
except TypeError, ValueError:  # Wrong!
    ...

作者可能尝试捕获 TypeErrorValueError 异常,但此代码实际上执行的操作不同:它将捕获 TypeError 并将生成的异常对象绑定到局部名称 "ValueError"ValueError 异常根本不会被捕获。正确的代码指定一个异常元组

try:
    ...
except (TypeError, ValueError):
    ...

发生此错误是因为此处逗号的使用是模棱两可的:它是表示解析树中的两个不同节点,还是表示一个作为元组的单个节点?

Python 3.0 通过将逗号替换为单词“as”来消除这种歧义。要捕获异常并将异常对象存储在变量 exc 中,您必须编写

try:
    ...
except TypeError as exc:
    ...

Python 3.0 将仅支持使用“as”,因此将第一个示例解释为捕获两个不同的异常。Python 2.6 同时支持逗号和“as”,因此现有代码将继续工作。因此,我们建议在编写仅使用 2.6 执行的新 Python 代码时使用“as”。

另请参阅

PEP 3110 - 在 Python 3000 中捕获异常

由 Collin Winter 编写和实现的 PEP。

PEP 3112:字节文字

Python 3.0 采用 Unicode 作为语言的基本字符串类型,并以不同的方式表示 8 位字面量,可以使用 b'string' 或使用 bytes 构造函数。为了未来的兼容性,Python 2.6 添加了 bytes 作为 str 类型的同义词,并且它也支持 b'' 表示法。

2.6 的 str 与 3.0 的 bytes 类型在多个方面有所不同;最值得注意的是,构造函数完全不同。在 3.0 中,bytes([65, 66, 67]) 的长度为 3,包含表示 ABC 的字节;在 2.6 中,bytes([65, 66, 67]) 返回表示列表的 str() 的 12 字节字符串。

2.6 中 bytes 的主要用途是编写诸如 isinstance(x, bytes) 之类的对象类型测试。这将有助于 2to3 转换器,因为转换器无法判断 2.x 代码中的字符串是包含字符还是 8 位字节;现在您可以使用 bytesstr 来准确表达您的意图,并且生成的代码在 Python 3.0 中也会是正确的。

还有一个 __future__ 导入,它会导致所有字符串字面量都变成 Unicode 字符串。这意味着可以使用 \u 转义序列来包含 Unicode 字符

from __future__ import unicode_literals

s = ('\u751f\u3080\u304e\u3000\u751f\u3054'
     '\u3081\u3000\u751f\u305f\u307e\u3054')

print len(s)               # 12 Unicode characters

在 C 级别,Python 3.0 将现有的 8 位字符串类型(在 Python 2.x 中称为 PyStringObject)重命名为 PyBytesObject。Python 2.6 使用 #define 来支持使用名称 PyBytesObject()PyBytes_Check()PyBytes_FromStringAndSize() 以及所有其他与字符串一起使用的函数和宏。

bytes 类型的实例是不可变的,就像字符串一样。新的 bytearray 类型存储可变的字节序列

>>> bytearray([65, 66, 67])
bytearray(b'ABC')
>>> b = bytearray(u'\u21ef\u3244', 'utf-8')
>>> b
bytearray(b'\xe2\x87\xaf\xe3\x89\x84')
>>> b[0] = '\xe3'
>>> b
bytearray(b'\xe3\x87\xaf\xe3\x89\x84')
>>> unicode(str(b), 'utf-8')
u'\u31ef \u3244'

字节数组支持大多数字符串类型的方法,例如 startswith()/endswith()find()/rfind(),以及一些列表的方法,例如 append()pop()reverse()

>>> b = bytearray('ABC')
>>> b.append('d')
>>> b.append(ord('e'))
>>> b
bytearray(b'ABCde')

还有一个相应的 C API,包含 PyByteArray_FromObject()PyByteArray_FromStringAndSize() 和各种其他函数。

另请参阅

PEP 3112 - Python 3000 中的字节字面量

PEP 由 Jason Orendorff 编写;由 Christian Heimes 反向移植到 2.6。

PEP 3116:新的 I/O 库

Python 的内置文件对象支持许多方法,但类文件对象不一定支持所有这些方法。模仿文件的对象通常支持 read()write(),但例如它们可能不支持 readline()。Python 3.0 在 io 模块中引入了一个分层 I/O 库,该库将缓冲和文本处理功能与基本的读取和写入操作分开。

io 模块提供了三个级别的抽象基类

  • RawIOBase 定义原始 I/O 操作:read()readinto()write()seek()tell()truncate()close()。此类的大多数方法通常会映射到单个系统调用。还有 readable()writable()seekable() 方法用于确定给定对象允许哪些操作。

    Python 3.0 针对文件和套接字为此类提供了具体的实现,但 Python 2.6 尚未以这种方式重构其文件和套接字对象。

  • BufferedIOBase 是一个抽象基类,它将数据缓冲在内存中以减少使用的系统调用次数,从而使 I/O 处理更加高效。它支持 RawIOBase 的所有方法,并添加了一个 raw 属性,该属性保存底层的原始对象。

    有五个具体的类实现了这个 ABC。BufferedWriterBufferedReader 用于支持只写或只读使用并且具有用于随机访问的 seek() 方法的对象。BufferedRandom 对象支持对同一个底层流进行读写访问,而 BufferedRWPair 用于诸如 TTY 之类的对象,这些对象具有对不连接的数据流进行操作的读取和写入操作。BytesIO 类支持对内存缓冲区进行读取、写入和查找。

  • TextIOBase:提供用于读取和写入字符串的函数(请记住,在 Python 3.0 中字符串将是 Unicode),并支持通用换行符TextIOBase 定义了 readline() 方法并支持对对象进行迭代。

    有两种具体的实现。TextIOWrapper 包装了一个缓冲的 I/O 对象,支持所有用于文本 I/O 的方法,并添加了一个 buffer 属性以访问底层对象。StringIO 只是将所有内容缓冲在内存中,而从不写入任何内容到磁盘。

    (在 Python 2.6 中,io.StringIO 是用纯 Python 实现的,因此速度很慢。因此,您现在应该坚持使用现有的 StringIO 模块或 cStringIO。在某个时候,Python 3.0 的 io 模块将被重写为 C 以提高速度,并且 C 实现可能会被反向移植到 2.x 版本中。)

在 Python 2.6 中,底层实现尚未重构为在 io 模块的类的基础上构建。提供该模块是为了更容易编写与 3.0 向前兼容的代码,并使开发人员免于编写自己的缓冲和文本 I/O 实现。

另请参阅

PEP 3116 - 新的 I/O

PEP 由 Daniel Stutzbach、Mike Verdone 和 Guido van Rossum 编写。代码由 Guido van Rossum、Georg Brandl、Walter Doerwald、Jeremy Hylton、Martin von Löwis、Tony Lownds 等人编写。

PEP 3118:修订的缓冲区协议

缓冲区协议是一个 C 级 API,它允许 Python 类型交换指向其内部表示的指针。例如,内存映射文件可以被视为字符缓冲区,这使得另一个模块(例如 re)可以将内存映射文件视为要搜索的字符串。

缓冲区协议的主要用户是诸如 NumPy 之类的数值处理包,这些包公开了数组的内部表示,以便调用者可以直接将数据写入数组,而不是通过较慢的 API。该 PEP 根据 NumPy 开发的经验更新了缓冲区协议,添加了许多新功能,例如指示数组的形状或锁定内存区域。

最重要的新的 C API 函数是 PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags),它接受一个对象和一组标志,并使用有关对象内存表示的信息填充 Py_buffer 结构。对象可以使用此操作来锁定内存,同时外部调用者可以修改内容,因此有一个对应的 PyBuffer_Release(Py_buffer *view) 来指示外部调用者已完成。

PyObject_GetBuffer()flags 参数指定了返回内存的约束。 一些例子是

  • PyBUF_WRITABLE 表示内存必须是可写的。

  • PyBUF_LOCK 请求对内存的只读或独占锁。

  • PyBUF_C_CONTIGUOUSPyBUF_F_CONTIGUOUS 请求 C 连续(最后维度变化最快)或 Fortran 连续(第一维度变化最快)的数组布局。

PyArg_ParseTuple() 的两个新的参数代码,s*z*,返回参数的锁定缓冲区对象。

另请参阅

PEP 3118 - 修订缓冲区协议

由 Travis Oliphant 和 Carl Banks 编写的 PEP;由 Travis Oliphant 实现。

PEP 3119:抽象基类

一些面向对象的语言(如 Java)支持接口,声明类具有给定的一组方法或支持给定的访问协议。抽象基类(或 ABC)是 Python 的等效功能。 ABC 支持包括一个 abc 模块,其中包含一个名为 ABCMeta 的元类,isinstance()issubclass() 内置函数对该元类的特殊处理,以及 Python 开发人员认为将广泛使用的一组基本 ABC。 未来版本的 Python 可能会添加更多的 ABC。

假设你有一个特定的类,并且想知道它是否支持字典式访问。然而,“字典式”这个词是模糊的。它可能意味着使用 obj[1] 访问项目有效。它是否意味着使用 obj[2] = value 设置项目有效?或者该对象将具有 keys()values()items() 方法?迭代变体(如 iterkeys())呢? copy()update()?使用 iter() 迭代对象?

Python 2.6 collections 模块包含许多不同的 ABC,这些 ABC 代表了这些区别。Iterable 表示一个类定义了 __iter__(),而 Container 表示该类定义了 __contains__() 方法,因此支持 x in y 表达式。获取项目、设置项目以及 keys()values()items() 的基本字典接口由 MutableMapping ABC 定义。

你可以从特定的 ABC 派生自己的类,以表明它们支持该 ABC 的接口

import collections

class Storage(collections.MutableMapping):
    ...

或者,你可以编写类而不从所需的 ABC 派生,而是通过调用 ABC 的 register() 方法注册该类

import collections

class Storage:
    ...

collections.MutableMapping.register(Storage)

对于你编写的类,从 ABC 派生可能更清晰。register() 方法在你编写可以描述现有类型或类的新 ABC 时,或者你想声明某个第三方类实现了 ABC 时非常有用。例如,如果你定义了一个 PrintableType ABC,则可以执行

# Register Python's types
PrintableType.register(int)
PrintableType.register(float)
PrintableType.register(str)

类应遵守 ABC 指定的语义,但 Python 无法检查这一点;类作者有责任理解 ABC 的要求并相应地实现代码。

要检查对象是否支持特定接口,你现在可以编写

def func(d):
    if not isinstance(d, collections.MutableMapping):
        raise ValueError("Mapping object expected, not %r" % d)

不要觉得你现在必须像上面的示例那样开始编写大量检查。Python 有一种强烈的“鸭子类型”传统,即从不进行显式类型检查,代码只是在对象上调用方法,相信这些方法会存在,如果不存在则会引发异常。明智地检查 ABC,并且只在绝对必要时才这样做。

你可以通过在类定义中使用 abc.ABCMeta 作为元类来编写自己的 ABC

from abc import ABCMeta, abstractmethod

class Drawable():
    __metaclass__ = ABCMeta

    @abstractmethod
    def draw(self, x, y, scale=1.0):
        pass

    def draw_doubled(self, x, y):
        self.draw(x, y, scale=2.0)


class Square(Drawable):
    def draw(self, x, y, scale):
        ...

在上面的 Drawable ABC 中,draw_doubled() 方法以其大小的两倍渲染对象,并且可以根据 Drawable 中描述的其他方法来实现。因此,实现此 ABC 的类不需要提供 draw_doubled() 的自己的实现,尽管它们可以这样做。但是,必须实现 draw();ABC 无法提供有用的通用实现。

你可以将 @abstractmethod 装饰器应用于必须实现的方法(如 draw());然后,Python 会为没有定义该方法的类引发异常。请注意,仅当你实际尝试创建缺少该方法的子类的实例时才会引发异常

>>> class Circle(Drawable):
...     pass
...
>>> c = Circle()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Circle with abstract methods draw
>>>

可以使用 @abstractproperty 装饰器声明抽象数据属性

from abc import abstractproperty
...

@abstractproperty
def readonly(self):
   return self._x

然后,子类必须定义一个 readonly() 属性。

另请参阅

PEP 3119 - 引入抽象基类

由 Guido van Rossum 和 Talin 编写的 PEP。由 Guido van Rossum 实现。由 Benjamin Aranguren 和 Alex Martelli 向后移植到 2.6。

PEP 3127:整数文字支持和语法

Python 3.0 更改了八进制(以 8 为基数)整数文字的语法,使用 “0o” 或 “0O” 而不是前导零作为前缀,并增加了对二进制(以 2 为基数)整数文字的支持,以 “0b” 或 “0B” 前缀表示。

Python 2.6 不会放弃对以 0 开头表示八进制数的支持,但它确实增加了对 “0o” 和 “0b” 的支持

>>> 0o21, 2*8 + 1
(17, 17)
>>> 0b101111
47

oct() 内置函数仍然返回以 0 开头的数字,而新的 bin() 内置函数返回数字的二进制表示形式

>>> oct(42)
'052'
>>> future_builtins.oct(42)
'0o52'
>>> bin(173)
'0b10101101'

当请求以 8 或 2 为基数时,或者当 base 参数为零时(表示应从字符串确定所用的基数),int()long() 内置函数现在将接受 “0o” 和 “0b” 前缀

>>> int ('0o52', 0)
42
>>> int('1101', 2)
13
>>> int('0b1101', 2)
13
>>> int('0b1101', 0)
13

另请参阅

PEP 3127 - 整数文字支持和语法

由 Patrick Maupin 编写的 PEP;由 Eric Smith 向后移植到 2.6。

PEP 3129:类装饰器

装饰器已从函数扩展到类。现在可以编写

@foo
@bar
class A:
  pass

这等效于

class A:
  pass

A = foo(bar(A))

另请参阅

PEP 3129 - 类装饰器

由 Collin Winter 编写的 PEP。

PEP 3141:数字的类型层次结构

Python 3.0 为受 Scheme 的数字塔启发的数字类型添加了几个抽象基类。这些类作为 numbers 模块向后移植到 2.6。

最通用的 ABC 是 Number。它没有定义任何操作,并且仅存在以允许通过执行 isinstance(obj, Number) 来检查对象是否为数字。

ComplexNumber 的子类。复数可以进行加法、减法、乘法、除法和求幂的基本运算,你可以检索实部和虚部并获得数字的共轭。Python 的内置复数类型是 Complex 的实现。

Real 类进一步派生自 Complex 类,并添加了仅适用于实数的操作:floor()trunc()、舍入、取模 N 的余数、向下取整除法以及比较。

Rational (有理数)类派生自 Real 类,具有 numerator(分子)和 denominator(分母)属性,并且可以转换为浮点数。Python 2.6 在 fractions 模块中添加了一个简单的有理数类 Fraction。(之所以称为 Fraction 而不是 Rational,是为了避免与 numbers.Rational 发生名称冲突。)

Integral (整数)类派生自 Rational 类,可以使用 <<>> 进行左移和右移,可以使用诸如 &| 的按位操作组合,并且可以用作数组索引和切片边界。

在 Python 3.0 中,PEP 稍微重新定义了现有的内置函数 round()math.floor()math.ceil(),并添加了一个新的函数 math.trunc(),该函数已被反向移植到 Python 2.6。math.trunc() 向零舍入,返回介于函数参数和零之间的最接近的 Integral 值。

另请参阅

PEP 3141 - 数字类型层次结构

由 Jeffrey Yasskin 撰写的 PEP。

Guile 手册中的 Scheme 数值塔

R5RS Scheme 规范中的 Scheme 数字数据类型

fractions 模块

为了完善数字类型层次结构,fractions 模块提供了一个有理数类。有理数将其值存储为构成一个分数的分母和分子,并且可以精确地表示诸如 2/3 这样的浮点数只能近似表示的数字。

Fraction 构造函数接受两个 Integral 值,它们将作为结果分数的分子和分母。

>>> from fractions import Fraction
>>> a = Fraction(2, 3)
>>> b = Fraction(2, 5)
>>> float(a), float(b)
(0.66666666666666663, 0.40000000000000002)
>>> a+b
Fraction(16, 15)
>>> a/b
Fraction(5, 3)

对于将浮点数转换为有理数,浮点类型现在有一个 as_integer_ratio() 方法,该方法返回一个分数的分子和分母,该分数的值与浮点数值相同。

>>> (2.5) .as_integer_ratio()
(5, 2)
>>> (3.1415) .as_integer_ratio()
(7074029114692207L, 2251799813685248L)
>>> (1./3) .as_integer_ratio()
(6004799503160661L, 18014398509481984L)

请注意,只能用浮点数近似的值(例如 1./3)不会被简化为近似的数字;该分数会尝试 **精确** 匹配浮点数值。

fractions 模块基于 Sjoerd Mullender 的一个实现,该实现长期存在于 Python 的 Demo/classes/ 目录中。这个实现由 Jeffrey Yasskin 进行了重大更新。

其他语言更改

对 Python 核心语言进行的一些较小的更改包括:

  • 包含 __main__.py 文件的目录和 zip 存档现在可以通过将其名称传递给解释器来直接执行。该目录或 zip 存档将自动作为 sys.path 中的第一个条目插入。(由 Andy Chu 提出建议和初始补丁,随后由 Phillip J. Eby 和 Nick Coghlan 修改;bpo-1739468。)

  • hasattr() 函数会捕获并忽略所有错误,假设它们意味着 __getattr__() 方法以某种方式失败,因此 hasattr() 的返回值将为 False。但是,此逻辑不应应用于 KeyboardInterruptSystemExit;Python 2.6 在 hasattr() 遇到这些异常时将不再丢弃它们。(由 Benjamin Peterson 修复;bpo-2196。)

  • 当使用 ** 语法来提供关键字参数调用函数时,不再需要使用 Python 字典;任何映射现在都可以工作。

    >>> def f(**kw):
    ...    print sorted(kw)
    ...
    >>> ud=UserDict.UserDict()
    >>> ud['a'] = 1
    >>> ud['b'] = 'string'
    >>> f(**ud)
    ['a', 'b']
    

    (由 Alexander Belopolsky 贡献;bpo-1686487。)

    在函数调用中,在 *args 参数之后提供关键字参数也变得合法。

    >>> def f(*args, **kw):
    ...     print args, kw
    ...
    >>> f(1,2,3, *(4,5,6), keyword=13)
    (1, 2, 3, 4, 5, 6) {'keyword': 13}
    

    以前,这会是一个语法错误。(由 Amaury Forgeot d'Arc 贡献;bpo-3473。)

  • 一个新的内置函数 next(iterator, [default]) 从指定的迭代器返回下一个项目。如果提供了 default 参数,则在 iterator 耗尽时将返回该参数;否则,将引发 StopIteration 异常。(在 bpo-2719 中反向移植。)

  • 元组现在具有与列表类型的 index()count() 方法相匹配的 index()count() 方法。

    >>> t = (0,1,2,3,4,0,1,2)
    >>> t.index(3)
    3
    >>> t.count(0)
    2
    

    (由 Raymond Hettinger 贡献)

  • 内置类型现在改进了对扩展切片语法的支持,接受 (start, stop, step) 的各种组合。以前,该支持是部分的,某些极端情况无法正常工作。(由 Thomas Wouters 实现。)

  • 属性现在具有三个属性,gettersetterdeleter,它们是装饰器,为向现有属性添加 getter、setter 或 deleter 函数提供了有用的快捷方式。你可以像这样使用它们:

    class C(object):
        @property
        def x(self):
            return self._x
    
        @x.setter
        def x(self, value):
            self._x = value
    
        @x.deleter
        def x(self):
            del self._x
    
    class D(C):
        @C.x.getter
        def x(self):
            return self._x * 2
    
        @x.setter
        def x(self, value):
            self._x = value / 2
    
  • 内置集合类型的几个方法现在接受多个可迭代对象:intersection()intersection_update()union()update()difference()difference_update()

    >>> s=set('1234567890')
    >>> s.intersection('abc123', 'cdf246')  # Intersection between all inputs
    set(['2'])
    >>> s.difference('246', '789')
    set(['1', '0', '3', '5'])
    

    (由 Raymond Hettinger 贡献。)

  • 添加了许多浮点数功能。float() 函数现在将字符串 nan 转换为 IEEE 754 非数字值,并将 +inf-inf 转换为正无穷大或负无穷大。这适用于任何具有 IEEE 754 语义的平台。(由 Christian Heimes 贡献;bpo-1635。)

    math 模块中的其他函数,如 isinf()isnan(),如果它们的浮点参数是无穷大或非数字(NaN),则返回 True。( bpo-1640)

    添加了转换函数,用于将浮点数转换为十六进制字符串(bpo-3008)。这些函数在不引入十进制和二进制之间转换导致的舍入误差的情况下,将浮点数转换为字符串表示形式,并从字符串表示形式转换回浮点数。浮点数有一个 hex() 方法,该方法返回字符串表示形式,并且 float.fromhex() 方法将字符串转换回数字。

    >>> a = 3.75
    >>> a.hex()
    '0x1.e000000000000p+1'
    >>> float.fromhex('0x1.e000000000000p+1')
    3.75
    >>> b=1./3
    >>> b.hex()
    '0x1.5555555555555p-2'
    
  • 一个数值上的改进:当在支持有符号零(-0 和 +0)的系统上从两个浮点数创建复数时,complex() 构造函数现在将保留零的符号。(由 Mark T. Dickinson 修复; bpo-1507.)

  • 从父类继承 __hash__() 方法的类可以设置 __hash__ = None 来表明该类不是可哈希的。这将使 hash(obj) 引发 TypeError 异常,并且该类不会被指示为实现了 Hashable ABC。

    当您定义了一个 __cmp__()__eq__() 方法,该方法按值而不是按身份比较对象时,您应该这样做。所有对象都有一个默认的哈希方法,该方法使用 id(obj) 作为哈希值。没有一种整洁的方法可以删除从父类继承的 __hash__() 方法,因此将 None 分配作为覆盖来实现。在 C 级别,扩展可以将 tp_hash 设置为 PyObject_HashNotImplemented()。(由 Nick Coghlan 和 Amaury Forgeot d’Arc 修复; bpo-2235.)

  • GeneratorExit 异常现在是 BaseException 的子类,而不是 Exception 的子类。这意味着执行 except Exception: 的异常处理程序不会无意中捕获 GeneratorExit。(由 Chad Austin 贡献; bpo-1537.)

  • 生成器对象现在具有 gi_code 属性,该属性引用支持生成器的原始代码对象。(由 Collin Winter 贡献; bpo-1473257.)

  • 内置函数 compile() 现在接受关键字参数以及位置参数。(由 Thomas Wouters 贡献; bpo-1444529.)

  • complex() 构造函数现在接受包含带括号的复数的字符串,这意味着 complex(repr(cplx)) 现在将往返值。例如,complex('(3+4j)') 现在返回 (3+4j) 的值。( bpo-1491866)

  • 字符串 translate() 方法现在接受 None 作为转换表参数,该参数被视为恒等变换。这使得更容易执行仅删除字符的操作。(由 Bengt Richter 贡献,由 Raymond Hettinger 实现; bpo-1193128.)

  • 内置函数 dir() 现在检查它接收的对象上是否有 __dir__() 方法。此方法必须返回包含对象有效属性名称的字符串列表,并让对象控制 dir() 生成的值。具有 __getattr__()__getattribute__() 方法的对象可以使用它来宣传它们将遵守的伪属性。( bpo-1591665)

  • 实例方法对象具有构成该对象和方法的新属性;im_self 的新同义词是 __self__,并且 im_func 也可作为 __func__ 使用。旧名称在 Python 2.6 中仍然受支持,但在 3.0 中已删除。

  • 一个不显眼的变化:当您在 class 语句中使用 locals() 函数时,生成的字典不再返回自由变量。(在这种情况下,自由变量是在 class 语句中引用但不是该类属性的变量。)

优化

  • warnings 模块已用 C 语言重写。这使得从解析器调用警告成为可能,也可能使解释器的启动速度更快。(由 Neal Norwitz 和 Brett Cannon 贡献; bpo-1631171.)

  • 类型对象现在有一个方法缓存,可以减少查找特定类的正确方法实现所需的工作;一旦缓存,解释器就不需要遍历基类来确定要调用的正确方法。如果修改了基类或类本身,则缓存会被清除,因此即使面对 Python 的动态特性,缓存也应保持正确。(最初由 Armin Rigo 实现优化,由 Kevin Jacobs 为 Python 2.6 更新; bpo-1700288.)

    默认情况下,此更改仅应用于 Python 核心中包含的类型。扩展模块可能不一定与此缓存兼容,因此它们必须显式地将 Py_TPFLAGS_HAVE_VERSION_TAG 添加到模块的 tp_flags 字段以启用方法缓存。(为了与方法缓存兼容,扩展模块的代码不得直接访问和修改它实现的任何类型的 tp_dict 成员。大多数模块不会这样做,但是 Python 解释器无法确定这一点。有关一些讨论,请参见 bpo-1878。)

  • 通过快速指针比较,使用关键字参数的函数调用速度明显加快,通常可以节省完整字符串比较的时间。(由 Raymond Hettinger 贡献,在 Antoine Pitrou 的初始实现之后; bpo-1819.)

  • 在 Need For Speed sprint 的努力下,struct 模块中的所有函数都已用 C 语言重写。(由 Raymond Hettinger 贡献。)

  • 一些标准内置类型现在在它们的类型对象中设置一个位。这加快了检查对象是否是这些类型之一的子类的速度。(由 Neal Norwitz 贡献。)

  • Unicode 字符串现在使用更快的代码来检测空格和换行符;这使得 split() 方法的速度提高了约 25%,splitlines() 方法的速度提高了 35%。 (由 Antoine Pitrou 贡献。) 通过为 Unicode 字符串的数据使用 pymalloc 减少了内存使用量。

  • with 语句现在将 __exit__() 方法存储在堆栈中,从而实现少量加速。(由 Jeffrey Yasskin 实现。)

  • 为了减少内存使用,垃圾回收器现在会在垃圾回收最高代对象时清除内部空闲列表。这可能会更快地将内存返回给操作系统。

解释器更改

保留了两个命令行选项供其他 Python 实现使用。 -J 开关已保留供 Jython 使用,用于特定于 Jython 的选项,例如传递给底层 JVM 的开关。 -X 已保留用于特定于 Python 特定实现的选项,例如 CPython、Jython 或 IronPython。如果将任一选项与 Python 2.6 一起使用,解释器将报告该选项当前未使用。

现在可以通过向 Python 解释器提供 -B 开关,或者在运行解释器之前设置 PYTHONDONTWRITEBYTECODE 环境变量,来阻止 Python 写入 .pyc.pyo 文件。 此设置在 Python 程序中可用作 sys.dont_write_bytecode 变量,并且 Python 代码可以更改该值来修改解释器的行为。(由 Neal Norwitz 和 Georg Brandl 贡献。)

可以通过在运行解释器之前设置 PYTHONIOENCODING 环境变量来指定用于标准输入、输出和标准错误的编码。该值应为 <encoding><encoding>:<errorhandler> 形式的字符串。encoding 部分指定编码的名称,例如 utf-8latin-1;可选的 errorhandler 部分指定如何处理编码无法处理的字符,应该为 “error”、“ignore” 或 “replace” 之一。(由 Martin von Löwis 贡献。)

新增和改进的模块

与每个版本一样,Python 的标准库都进行了一些增强和错误修复。以下是按模块名称字母顺序排列的最值得注意的更改的部分列表。有关更完整的更改列表,请查阅源代码树中的 Misc/NEWS 文件,或浏览 Subversion 日志以了解所有详细信息。

  • asyncoreasynchat 模块再次得到积极维护,并应用了一些补丁和错误修复。(由 Josiah Carlson 维护;有关一个补丁,请参见 bpo-1736190。)

  • bsddb 模块也有一个新的维护者 Jesús Cea Avión,并且该软件包现在可以作为独立软件包使用。该软件包的网页为 www.jcea.es/programacion/pybsddb.htm。计划在 Python 3.0 中从标准库中删除该软件包,因为它的发布速度比 Python 快得多。

    bsddb.dbshelve 模块现在使用可用的最高 pickle 协议,而不是限制为协议 1。(由 W. Barnes 贡献。)

  • cgi 模块现在将从 HTTP POST 请求的查询字符串中读取变量。这使得可以使用包含查询字符串的 URL 来进行表单操作,例如 “/cgi-bin/add.py?category=1”。(由 Alexandre Fiori 和 Nubis 贡献;bpo-1817。)

    parse_qs()parse_qsl() 函数已从 cgi 模块重新定位到 urlparse 模块。仍然在 cgi 模块中可用的版本将在 2.6 中触发 PendingDeprecationWarning 消息(bpo-600362)。

  • cmath 模块经过了广泛的修订,由 Mark Dickinson 和 Christian Heimes 贡献。添加了五个新函数

    • polar() 将复数转换为极坐标形式,返回复数的模和参数。

    • rect() 执行相反的操作,将模数、参数对转换回相应的复数。

    • phase() 返回复数的参数(也称为角度)。

    • 如果其参数的实部或虚部为 NaN,则 isnan() 返回 True。

    • 如果其参数的实部或虚部为无穷大,则 isinf() 返回 True。

    修订还改进了 cmath 模块的数值稳健性。对于所有函数,结果的实部和虚部在可能的情况下都精确到几个最小精度单位 (ulp) 以内。有关详细信息,请参见 bpo-1381asinh()atanh(): 和 atan() 的分支切割也已更正。

    该模块的测试已大大扩展;近 2000 个新的测试用例对代数函数进行了练习。

    在 IEEE 754 平台上,cmath 模块现在以与 C99 标准的附录“G”一致的方式处理 IEEE 754 特殊值和浮点异常。

  • collections 模块中的一种新数据类型:namedtuple(typename, fieldnames) 是一个工厂函数,它创建标准元组的子类,这些子类的字段可以通过名称以及索引访问。例如

    >>> var_type = collections.namedtuple('variable',
    ...             'id name type size')
    >>> # Names are separated by spaces or commas.
    >>> # 'id, name, type, size' would also work.
    >>> var_type._fields
    ('id', 'name', 'type', 'size')
    
    >>> var = var_type(1, 'frequency', 'int', 4)
    >>> print var[0], var.id    # Equivalent
    1 1
    >>> print var[2], var.type  # Equivalent
    int int
    >>> var._asdict()
    {'size': 4, 'type': 'int', 'id': 1, 'name': 'frequency'}
    >>> v2 = var._replace(name='amplitude')
    >>> v2
    variable(id=1, name='amplitude', type='int', size=4)
    

    标准库中一些返回元组的位置已被修改为返回 namedtuple() 实例。例如,Decimal.as_tuple() 方法现在返回一个名为 signdigitsexponent 字段的命名元组。

    (由 Raymond Hettinger 贡献。)

  • collections 模块的另一个更改是,deque 类型现在支持可选的 maxlen 参数;如果提供,则 deque 的大小将被限制为不超过 maxlen 项。向完整的 deque 添加更多项会导致旧项被丢弃。

    >>> from collections import deque
    >>> dq=deque(maxlen=3)
    >>> dq
    deque([], maxlen=3)
    >>> dq.append(1); dq.append(2); dq.append(3)
    >>> dq
    deque([1, 2, 3], maxlen=3)
    >>> dq.append(4)
    >>> dq
    deque([2, 3, 4], maxlen=3)
    

    (由 Raymond Hettinger 贡献。)

  • Cookie 模块的 Morsel 对象现在支持 httponly 属性。在某些浏览器中,无法通过 JavaScript 代码访问或操作设置此属性的 cookie。(由 Arvin Schnell 贡献;bpo-1638033。)

  • curses 模块中的一个新的窗口方法 chgat(),更改单行上一定数量字符的显示属性。(由 Fabian Kreutz 贡献。)

    # Boldface text starting at y=0,x=21
    # and affecting the rest of the line.
    stdscr.chgat(0, 21, curses.A_BOLD)
    

    curses.textpad 模块中的 Textbox 类现在支持在插入模式和覆盖模式下编辑。通过在创建 Textbox 实例时为 insert_mode 参数提供 true 值来启用插入模式。

  • datetime 模块的 strftime() 方法现在支持 %f 格式代码,该代码扩展为对象中的微秒数,在左侧用零填充到六位。(由 Skip Montanaro 贡献;bpo-1158。)

  • decimal 模块已更新至 通用十进制规范 的 1.66 版本。新功能包括一些基本数学函数的方法,例如 exp()log10()

    >>> Decimal(1).exp()
    Decimal("2.718281828459045235360287471")
    >>> Decimal("2.7182818").ln()
    Decimal("0.9999999895305022877376682436")
    >>> Decimal(1000).log10()
    Decimal("3")
    

    Decimal 对象的 as_tuple() 方法现在返回一个带有 signdigitsexponent 字段的命名元组。

    (由 Facundo Batista 和 Mark Dickinson 实现。Raymond Hettinger 添加了命名元组支持。)

  • difflib 模块的 SequenceMatcher 类现在返回表示匹配项的命名元组,包含 absize 属性。(由 Raymond Hettinger 贡献。)

  • 一个可选的 timeout 参数(以秒为单位指定超时时间)已添加到 ftplib.FTP 类构造函数以及 connect() 方法中。(由 Facundo Batista 添加。)此外,FTP 类的 storbinary()storlines() 方法现在接受一个可选的 callback 参数,该参数将在数据发送后针对每个数据块被调用。(由 Phil Schwartz 贡献;bpo-1221598。)

  • reduce() 内置函数也可在 functools 模块中使用。在 Python 3.0 中,该内置函数已被删除,reduce() 只能从 functools 中获得;目前没有计划在 2.x 系列中删除内置函数。(由 Christian Heimes 修复;bpo-1739906。)

  • 在可能的情况下,getpass 模块现在将使用 /dev/tty 来打印提示消息并读取密码,如果失败则会回退到标准错误和标准输入。如果密码可能会回显到终端,则会在显示提示符之前打印警告。(由 Gregory P. Smith 贡献。)

  • 如果使用了 Unicode 路径并且在目录中匹配了 Unicode 文件名,则 glob.glob() 函数现在可以返回 Unicode 文件名。(bpo-1001604

  • heapq 模块中的一个新函数 merge(iter1, iter2, ...) 接受任意数量的可迭代对象(这些对象以排序顺序返回数据),并返回一个新的生成器,该生成器也以排序顺序返回所有迭代器的内容。例如

    >>> list(heapq.merge([1, 3, 5, 9], [2, 8, 16]))
    [1, 2, 3, 5, 8, 9, 16]
    

    另一个新函数 heappushpop(heap, item)item 推送到 heap 上,然后弹出并返回最小的项。这比调用 heappush()heappop() 更高效。

    heapq 现在实现为仅使用小于比较,而不是之前使用的小于或等于比较。这使得 heapq 的类型使用与 list.sort() 方法匹配。(由 Raymond Hettinger 贡献。)

  • 一个可选的 timeout 参数(以秒为单位指定超时时间)已添加到 httplib.HTTPConnectionHTTPSConnection 类构造函数中。(由 Facundo Batista 添加。)

  • 大多数 inspect 模块的函数(例如 getmoduleinfo()getargs())现在返回命名元组。除了像元组一样工作外,返回值元素还可以作为属性访问。(由 Raymond Hettinger 贡献。)

    模块中的一些新函数包括 isgenerator()isgeneratorfunction()isabstract()

  • itertools 模块增加了几个新函数。

    izip_longest(iter1, iter2, ...[, fillvalue]) 从每个元素创建元组;如果某些可迭代对象比其他对象短,则将缺失的值设置为 fillvalue。例如

    >>> tuple(itertools.izip_longest([1,2,3], [1,2,3,4,5]))
    ((1, 1), (2, 2), (3, 3), (None, 4), (None, 5))
    

    product(iter1, iter2, ..., [repeat=N]) 返回提供的可迭代对象的笛卡尔积,这是一个包含从每个可迭代对象返回的元素的所有可能组合的元组集合。

    >>> list(itertools.product([1,2,3], [4,5,6]))
    [(1, 4), (1, 5), (1, 6),
     (2, 4), (2, 5), (2, 6),
     (3, 4), (3, 5), (3, 6)]
    

    可选的 repeat 关键字参数用于重复 N 次,获取一个可迭代对象或一组可迭代对象与自身的乘积。对于单个可迭代对象参数,返回 N 元组

    >>> list(itertools.product([1,2], repeat=3))
    [(1, 1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2),
     (2, 1, 1), (2, 1, 2), (2, 2, 1), (2, 2, 2)]
    

    对于两个可迭代对象,返回 2N 元组。

    >>> list(itertools.product([1,2], [3,4], repeat=2))
    [(1, 3, 1, 3), (1, 3, 1, 4), (1, 3, 2, 3), (1, 3, 2, 4),
     (1, 4, 1, 3), (1, 4, 1, 4), (1, 4, 2, 3), (1, 4, 2, 4),
     (2, 3, 1, 3), (2, 3, 1, 4), (2, 3, 2, 3), (2, 3, 2, 4),
     (2, 4, 1, 3), (2, 4, 1, 4), (2, 4, 2, 3), (2, 4, 2, 4)]
    

    combinations(iterable, r)iterable 的元素返回长度为 r 的子序列。

    >>> list(itertools.combinations('123', 2))
    [('1', '2'), ('1', '3'), ('2', '3')]
    >>> list(itertools.combinations('123', 3))
    [('1', '2', '3')]
    >>> list(itertools.combinations('1234', 3))
    [('1', '2', '3'), ('1', '2', '4'),
     ('1', '3', '4'), ('2', '3', '4')]
    

    permutations(iter[, r]) 返回可迭代对象元素的所有长度为 r 的排列。如果未指定 r,则默认为可迭代对象产生的元素数量。

    >>> list(itertools.permutations([1,2,3,4], 2))
    [(1, 2), (1, 3), (1, 4),
     (2, 1), (2, 3), (2, 4),
     (3, 1), (3, 2), (3, 4),
     (4, 1), (4, 2), (4, 3)]
    

    itertools.chain(*iterables)itertools 中已有的函数,在 Python 2.6 中获得了一个新的构造函数。itertools.chain.from_iterable(iterable) 接受一个应返回其他可迭代对象的单个可迭代对象。chain() 将返回第一个可迭代对象的所有元素,然后返回第二个可迭代对象的所有元素,依此类推。

    >>> list(itertools.chain.from_iterable([[1,2,3], [4,5,6]]))
    [1, 2, 3, 4, 5, 6]
    

    (全部由 Raymond Hettinger 贡献。)

  • logging 模块的 FileHandler 类及其子类 WatchedFileHandlerRotatingFileHandlerTimedRotatingFileHandler 现在在其构造函数中有一个可选的 delay 参数。如果 delay 为 true,则会延迟打开日志文件,直到第一次调用 emit()。(由 Vinay Sajip 贡献。)

    TimedRotatingFileHandler 还有一个 utc 构造函数参数。如果参数为 true,则在确定午夜何时发生以及生成文件名时将使用 UTC 时间;否则将使用本地时间。

  • math 模块添加了几个新函数

    • isinf()isnan() 分别确定给定的浮点数是否为(正或负)无穷大或 NaN(非数字)。

    • copysign() 复制 IEEE 754 数字的符号位,返回 x 的绝对值与 y 的符号位的组合。例如,math.copysign(1, -0.0) 返回 -1.0。(由 Christian Heimes 贡献。)

    • factorial() 计算一个数的阶乘。(由 Raymond Hettinger 贡献;bpo-2138。)

    • fsum() 从可迭代对象中求和数字流,并注意通过使用部分和来避免精度损失。(由 Jean Brouwers、Raymond Hettinger 和 Mark Dickinson 贡献;bpo-2819。)

    • acosh()asinh()atanh() 计算反双曲函数。

    • log1p() 返回 1+x 的自然对数(底为 e)。

    • trunc() 将一个数字向零舍入,返回最接近的 Integral 类型值,该值介于函数的参数和零之间。作为 PEP 3141 数字类型层次结构 向后移植的一部分添加。

  • math 模块已得到改进,可以在不同平台上提供更一致的行为,尤其是在处理浮点异常和 IEEE 754 特殊值方面。

    在可能的情况下,该模块遵循 C99 标准关于 754 特殊值的建议。例如,sqrt(-1.) 现在应该在几乎所有平台上给出 ValueError,而 sqrt(float('NaN')) 应该在所有 IEEE 754 平台上返回 NaN。如果 C99 标准的附件“F”建议发出“除以零”或“无效”信号,则 Python 将引发 ValueError。如果 C99 标准的附件“F”建议发出“溢出”信号,则 Python 将引发 OverflowError。(参见 bpo-711019bpo-1640。)

    (由 Christian Heimes 和 Mark Dickinson 贡献。)

  • mmap 对象现在有一个 rfind() 方法,该方法从字符串末尾开始向后搜索子字符串。find() 方法还增加了一个 end 参数,用于指定停止搜索的索引。(由 John Lenton 贡献。)

  • operator 模块增加了一个 methodcaller() 函数,该函数接受一个名称和一个可选的参数集合,返回一个可调用对象,该对象将在传递给它的任何参数上调用指定名称的函数。例如

    >>> # Equivalent to lambda s: s.replace('old', 'new')
    >>> replacer = operator.methodcaller('replace', 'old', 'new')
    >>> replacer('old wine in old bottles')
    'new wine in new bottles'
    

    (由 Georg Brandl 贡献,根据 Gregory Petrosyan 的建议。)

    attrgetter() 函数现在接受点号分隔的名称,并执行相应的属性查找

    >>> inst_name = operator.attrgetter(
    ...        '__class__.__name__')
    >>> inst_name('')
    'str'
    >>> inst_name(help)
    '_Helper'
    

    (由 Georg Brandl 贡献,根据 Barry Warsaw 的建议。)

  • os 模块现在包装了几个新的系统调用。fchmod(fd, mode)fchown(fd, uid, gid) 更改打开文件的模式和所有权,而 lchmod(path, mode) 更改符号链接的模式。(由 Georg Brandl 和 Christian Heimes 贡献。)

    chflags()lchflags() 是相应系统调用的包装器(如果可用),用于更改文件上设置的标志。标志值的常量在 stat 模块中定义;一些可能的值包括 UF_IMMUTABLE 表示该文件可能不会被更改,以及 UF_APPEND 表示只能将数据附加到该文件。(由 M. Levinson 贡献。)

    os.closerange(low, high) 有效地关闭从 lowhigh 的所有文件描述符,忽略任何错误,且不包括 high 本身。此函数现在被 subprocess 模块使用,以加快进程的启动速度。(由 Georg Brandl 贡献;bpo-1663329。)

  • os.environ 对象的 clear() 方法现在除了清除对象的键之外,还将使用 os.unsetenv() 来取消设置环境变量。(由 Martin Horcicka 贡献;bpo-1181。)

  • os.walk() 函数现在有一个 followlinks 参数。如果设置为 True,它将跟随指向目录的符号链接,并访问该目录的内容。为了向后兼容,该参数的默认值为 false。请注意,如果存在指向父目录的符号链接,则该函数可能会陷入无限递归。(bpo-1273829

  • os.path 模块中,splitext() 函数已更改为不在前导句点字符上分割。这在操作 Unix 的点文件时会产生更好的结果。例如,os.path.splitext('.ipython') 现在返回 ('.ipython', '') 而不是 ('', '.ipython')。(bpo-1115886

    一个新的函数,os.path.relpath(path, start='.'),返回从 start 路径(如果提供)或从当前工作目录到目标 path 的相对路径。(由 Richard Barran 贡献;bpo-1339796。)

    在 Windows 上,os.path.expandvars() 现在将扩展以“%var%”形式给出的环境变量,并将“~user”扩展为用户的家目录路径。(由 Josiah Carlson 贡献;bpo-957650。)

  • pdb 模块提供的 Python 调试器增加了一个新命令:“run”重新启动正在调试的 Python 程序,并且可以选择为该程序提供新的命令行参数。(由 Rocky Bernstein 贡献;bpo-1393667。)

  • 用于开始调试回溯的 pdb.post_mortem() 函数,如果没有提供回溯,现在将使用 sys.exc_info() 返回的回溯。(由 Facundo Batista 贡献;bpo-1106316。)

  • pickletools 模块现在有一个 optimize() 函数,该函数接受包含 pickle 的字符串,并删除一些未使用的操作码,返回包含相同数据结构的较短 pickle。(由 Raymond Hettinger 贡献。)

  • 一个 get_data() 函数被添加到 pkgutil 模块中,该函数返回与已安装的 Python 包一起包含的资源文件的内容。例如

    >>> import pkgutil
    >>> print pkgutil.get_data('test', 'exception_hierarchy.txt')
    BaseException
     +-- SystemExit
     +-- KeyboardInterrupt
     +-- GeneratorExit
     +-- Exception
          +-- StopIteration
          +-- StandardError
     ...
    

    (由 Paul Moore 贡献;bpo-2439。)

  • pyexpat 模块的 Parser 对象现在允许设置它们的 buffer_size 属性,以更改用于保存字符数据的缓冲区大小。(由 Achim Gaedke 贡献;bpo-1137。)

  • 现在,Queue 模块提供了可以按不同顺序检索条目的队列变体。PriorityQueue 类将排队的项存储在一个堆中,并按优先级顺序检索它们,而 LifoQueue 则首先检索最近添加的条目,这意味着它的行为类似于堆栈。(由 Raymond Hettinger 贡献。)

  • random 模块的 Random 对象现在可以在 32 位系统上进行 pickle 序列化,并在 64 位系统上进行反序列化,反之亦然。不幸的是,此更改还意味着 Python 2.6 的 Random 对象无法在早期版本的 Python 上正确反序列化。(由 Shawn Ligocki 贡献;bpo-1727780。)

    新的 triangular(low, high, mode) 函数返回符合三角分布的随机数。返回的值在 *low* 和 *high* 之间,不包括 *high* 本身,并且以 *mode* 作为分布中最常出现的值。(由 Wladmir van der Laan 和 Raymond Hettinger 贡献;bpo-1681432。)

  • re 模块执行的长时间正则表达式搜索会检查信号是否已传递,因此现在可以中断耗时的搜索。(由 Josh Hoyt 和 Ralf Schmitt 贡献;bpo-846388。)

    正则表达式模块是通过为小型特定于正则表达式的虚拟机编译字节码来实现的。不受信任的代码可以直接创建恶意的字节码字符串并导致崩溃,因此 Python 2.6 包括了正则表达式字节码的验证器。(由 Guido van Rossum 从 Google App Engine 的工作贡献;bpo-3487。)

  • rlcompleter 模块的 Completer.complete() 方法现在将忽略评估名称时触发的异常。(由 Lorenz Quack 修复;bpo-2250。)

  • sched 模块的 scheduler 实例现在具有只读的 queue 属性,该属性返回调度程序队列的内容,表示为具有字段 (time, priority, action, argument) 的命名元组列表。(由 Raymond Hettinger 贡献;bpo-1861。)

  • select 模块现在具有用于 Linux epoll() 和 BSD kqueue() 系统调用的包装函数。将 modify() 方法添加到现有的 poll 对象;pollobj.modify(fd, eventmask) 接受文件描述符或文件对象和一个事件掩码,修改该文件的记录事件掩码。(由 Christian Heimes 贡献;bpo-1657。)

  • shutil.copytree() 函数现在有一个可选的 *ignore* 参数,该参数接受一个可调用对象。这个可调用对象将接收每个目录路径和目录内容的列表,并返回将忽略(不复制)的名称列表。

    shutil 模块还提供了 ignore_patterns() 函数,用于此新参数。ignore_patterns() 接受任意数量的 glob 样式模式,并返回一个可调用对象,该对象将忽略与这些模式中的任何一个匹配的任何文件和目录。以下示例复制目录树,但跳过 .svn 目录和 Emacs 备份文件,这些文件的名称以“~”结尾

    shutil.copytree('Doc/library', '/tmp/library',
                    ignore=shutil.ignore_patterns('*~', '.svn'))
    

    (由 Tarek Ziadé 贡献;bpo-2663。)

  • 将信号处理与 Tkinter 或 GTk+ 等 GUI 处理事件循环集成一直是一个问题;大多数软件最终会轮询,每隔几分之一秒唤醒一次,以检查是否发生了任何 GUI 事件。signal 模块现在可以使此操作更有效率。调用 signal.set_wakeup_fd(fd) 会设置要使用的文件描述符;当收到信号时,会将一个字节写入该文件描述符。还有一个 C 级函数 PySignal_SetWakeupFd(),用于设置描述符。

    事件循环将通过打开管道来创建两个描述符(一个用于读取,一个用于写入)来使用此功能。可写描述符将传递给 set_wakeup_fd(),可读描述符将添加到事件循环通过 select()poll() 监视的描述符列表中。接收到信号时,将写入一个字节,并唤醒主事件循环,避免了轮询的需要。

    (由 Adam Olsen 贡献;bpo-1583。)

    现在可以从 Python 代码中使用 siginterrupt() 函数,并允许更改信号是否可以中断系统调用。(由 Ralf Schmitt 贡献。)

    还添加了 setitimer()getitimer() 函数(在它们可用的地方)。setitimer() 允许设置间隔计时器,这些计时器会在指定时间(以实际时间、消耗的进程时间或组合的进程+系统时间衡量)后向进程发送信号。(由 Guilherme Polo 贡献;bpo-2240。)

  • 由于添加了 SMTP_SSL 类,smtplib 模块现在支持通过 SSL 的 SMTP。此类支持与现有 SMTP 类相同的接口。(由 Monty Taylor 贡献。)两个类的构造函数还有一个可选的 timeout 参数,该参数指定初始连接尝试的超时时间(以秒为单位)。(由 Facundo Batista 贡献。)

    该模块中还添加了 LMTP 协议 (RFC 2033) 的实现。LMTP 在不管理邮件队列的代理之间传输电子邮件时,用来代替 SMTP。(LMTP 由 Leif Hedstrom 实现;bpo-957003。)

    SMTP.starttls() 现在符合 RFC 3207,并忘记从服务器获得的任何知识(而不是从 TLS 协商本身获得的)。(由 Bill Fenner 贡献;bpo-829951。)

  • socket 模块现在支持 TIPC (https://tipc.sourceforge.net/),这是一种为集群环境设计的高性能非基于 IP 的协议。TIPC 地址是 4 元组或 5 元组。(由 Alberto Bertogli 贡献;bpo-1646。)

    新函数 create_connection() 接受一个地址,并使用可选的超时值连接到该地址,然后返回连接的套接字对象。此函数还会查找地址的类型,并根据需要使用 IPv4 或 IPv6 连接到它。将您的代码更改为使用 create_connection() 而不是 socket(socket.AF_INET, ...) 可能是使您的代码与 IPv6 兼容所需的一切。

  • 现在,SocketServer 模块中的基类支持在服务器的 timeout 属性指定的非活动时间段之后调用 handle_timeout() 方法。(由 Michael Pomraning 贡献。) serve_forever() 方法现在接受一个以秒为单位的可选轮询间隔,用于控制服务器检查关闭请求的频率。(由 Pedro Werneck 和 Jeffrey Yasskin 贡献;bpo-742598bpo-1193577。)

  • 由 Gerhard Häring 维护的 sqlite3 模块已从 Python 2.5 中的 2.3.2 版本更新到 2.4.1 版本。

  • struct 模块现在支持 C99 的 _Bool 类型,使用格式字符 '?'。(由 David Remahl 贡献。)

  • subprocess 模块提供的 Popen 对象现在具有 terminate()kill()send_signal() 方法。在 Windows 上,send_signal() 仅支持 SIGTERM 信号,并且所有这些方法都是 Win32 API 函数 TerminateProcess() 的别名。(由 Christian Heimes 贡献。)

  • sys 模块中的一个新变量 float_info 是一个对象,其中包含从 float.h 文件中派生的有关平台浮点支持的信息。此对象的属性包括 mant_dig(尾数中的位数)、epsilon(1.0 和下一个可表示的最大值之间的最小差值)以及其他几个属性。(由 Christian Heimes 贡献;bpo-1534。)

    另一个新变量 dont_write_bytecode 控制 Python 在导入模块时是否写入任何 .pyc.pyo 文件。如果此变量为 true,则不会写入编译后的文件。该变量最初由向 Python 解释器提供 -B 开关,或在运行解释器之前设置 PYTHONDONTWRITEBYTECODE 环境变量来在启动时设置。 Python 代码随后可以更改此变量的值,以控制是否写入字节码文件。(由 Neal Norwitz 和 Georg Brandl 贡献。)

    通过读取名为元组的属性,可以获得有关提供给 Python 解释器的命令行参数的信息,该元组可作为 sys.flags 使用。例如,如果 Python 在详细模式下执行,则 verbose 属性为 true,如果在调试模式下,则 debug 为 true,等等。这些属性都是只读的。(由 Christian Heimes 贡献。)

    一个新函数 getsizeof() 接受一个 Python 对象,并返回该对象使用的内存量,以字节为单位。内置对象返回正确的结果;第三方扩展可能无法返回正确的结果,但可以定义一个 __sizeof__() 方法来返回对象的大小。(由 Robert Schuppenies 贡献;bpo-2898。)

    现在可以通过调用 sys.getprofile()sys.gettrace() 来确定当前的分析器和跟踪器函数。(由 Georg Brandl 贡献;bpo-1648。)

  • tarfile 模块现在除了已经支持的 POSIX.1-1988 (ustar) 和 GNU tar 格式之外,还支持 POSIX.1-2001 (pax) tar 文件。默认格式为 GNU tar;指定 format 参数以使用不同的格式打开文件。

    tar = tarfile.open("output.tar", "w",
                       format=tarfile.PAX_FORMAT)
    

    新的 encodingerrors 参数指定字符转换的编码和错误处理方案。'strict''ignore''replace' 是 Python 处理错误的三个标准方法;'utf-8' 是一个特殊值,它用 UTF-8 表示形式替换坏字符。(进行字符转换是因为 PAX 格式支持 Unicode 文件名,默认为 UTF-8 编码。)

    TarFile.add() 方法现在接受一个 exclude 参数,该参数是一个函数,可用于从存档中排除某些文件名。该函数必须接受一个文件名,如果应排除该文件,则返回 true,如果应存档该文件,则返回 false。该函数将应用于最初传递给 add() 的名称以及递归添加的目录中的文件名称。

    (所有更改均由 Lars Gustäbel 贡献。)

  • telnetlib.Telnet 类构造函数添加了一个可选的 timeout 参数,该参数指定以秒为单位的超时时间。(由 Facundo Batista 添加。)

  • tempfile.NamedTemporaryFile 类通常会在文件关闭时删除它创建的临时文件。现在可以通过向构造函数传递 delete=False 来更改此行为。(由 Damien Miller 贡献;bpo-1537850。)

    一个新类 SpooledTemporaryFile 的行为类似于临时文件,但将其数据存储在内存中,直到超出最大大小。达到该限制后,内容将写入磁盘上的临时文件。(由 Dustin J. Mitchell 贡献。)

    NamedTemporaryFileSpooledTemporaryFile 类都充当上下文管理器,因此可以编写 with tempfile.NamedTemporaryFile() as tmp: ...。(由 Alexander Belopolsky 贡献;bpo-2021。)

  • test.test_support 模块获得了许多可用于编写测试的上下文管理器。EnvironmentVarGuard() 是一个上下文管理器,可临时更改环境变量,并自动将其还原为旧值。

    另一个上下文管理器 TransientResource 可以围绕对可能可用也可能不可用的资源的调用;它将捕获并忽略指定的异常列表。例如,网络测试在连接到外部网站时可能会忽略某些失败。

    with test_support.TransientResource(IOError,
                                    errno=errno.ETIMEDOUT):
        f = urllib.urlopen('https://sf.net')
        ...
    

    最后,check_warnings() 重置 warning 模块的警告过滤器,并返回一个将记录所有触发的警告消息的对象(bpo-3781)。

    with test_support.check_warnings() as wrec:
        warnings.simplefilter("always")
        # ... code that triggers a warning ...
        assert str(wrec.message) == "function is outdated"
        assert len(wrec.warnings) == 1, "Multiple warnings raised"
    

    (由 Brett Cannon 贡献。)

  • 现在,textwrap 模块可以通过指定 drop_whitespace=False 作为参数来保留新创建行的开头和结尾处现有的空白。

    >>> S = """This  sentence  has a bunch   of
    ...   extra   whitespace."""
    >>> print textwrap.fill(S, width=15)
    This  sentence
    has a bunch
    of    extra
    whitespace.
    >>> print textwrap.fill(S, drop_whitespace=False, width=15)
    This  sentence
      has a bunch
       of    extra
       whitespace.
    >>>
    

    (由 Dwayne Bailey 贡献;bpo-1581073。)

  • threading 模块的 API 正在更改为使用诸如 daemon 之类的属性,而不是 setDaemon()isDaemon() 方法,并且一些方法已重命名为使用下划线而不是驼峰式命名;例如,activeCount() 方法已重命名为 active_count()。该模块的 2.6 和 3.0 版本都支持相同的属性和重命名方法,但不会删除旧方法。Python 3.x 中旧 API 的弃用日期尚未确定;旧 API 不会在任何 2.x 版本中删除。(由多人执行,最值得注意的是 Benjamin Peterson。)

    threading 模块的 Thread 对象获得了一个 ident 属性,该属性返回线程的标识符,一个非零整数。(由 Gregory P. Smith 贡献;bpo-2871。)

  • timeit 模块现在接受可调用对象以及字符串作为要计时的语句和设置代码。添加了两个便利函数来创建 Timer 实例:repeat(stmt, setup, time, repeat, number)timeit(stmt, setup, time, number) 创建一个实例并调用相应的方法。(由 Erik Demaine 贡献;bpo-1533909。)

  • Tkinter 模块现在接受列表和元组作为选项,在将结果值传递给 Tcl/Tk 之前用空格分隔元素。(由 Guilherme Polo 贡献;bpo-2906。)

  • 用于海龟图形的 turtle 模块由 Gregor Lingl 大大增强。该模块的新功能包括

    • 更好地动画海龟的移动和旋转。

    • 使用新的 delay()tracer()speed() 方法控制海龟的移动。

    • 能够为海龟设置新的形状,并定义新的坐标系。

    • 海龟现在有一个 undo() 方法,可以回滚操作。

    • 简单支持响应诸如鼠标和键盘活动之类的输入事件,从而可以编写简单的游戏。

    • 可以使用 turtle.cfg 文件来自定义海龟屏幕的起始外观。

    • 该模块的文档字符串可以替换为已翻译成另一种语言的新文档字符串。

    bpo-1513695

  • urllib.urlopen 函数和 urllib.ftpwrapper 类构造函数,以及 urllib2.urlopen 函数中添加了一个可选的 timeout 参数。该参数指定以秒为单位的超时时间。例如

    >>> u = urllib2.urlopen("http://slow.example.com",
                            timeout=3)
    Traceback (most recent call last):
      ...
    urllib2.URLError: <urlopen error timed out>
    >>>
    

    (由 Facundo Batista 添加。)

  • unicodedata 模块提供的 Unicode 数据库已更新到 5.1.0 版本。(由 Martin von Löwis 更新;bpo-3811。)

  • warnings 模块的 formatwarning()showwarning() 获得了可选的 *line* 参数,该参数可用于提供源代码的行。(作为 bpo-1631171 的一部分添加,它在 C 代码中重新实现了 warnings 模块的一部分。)

    一个新函数 catch_warnings() 是一个用于测试目的的上下文管理器,允许您临时修改警告过滤器,然后恢复其原始值(bpo-3781)。

  • 通过将 False 作为 *bind_and_activate* 构造函数参数传递,现在可以阻止 XML-RPC 的 SimpleXMLRPCServerDocXMLRPCServer 类立即打开并绑定到它们的套接字。这可以用于在调用 server_bind()server_activate() 方法以打开套接字并开始侦听连接之前,修改实例的 allow_reuse_address 属性。(由 Peter Parente 贡献;bpo-1599845。)

    SimpleXMLRPCServer 还有一个 _send_traceback_header 属性;如果为 true,则异常和格式化的回溯将作为 HTTP 标头 “X-Exception” 和 “X-Traceback” 返回。此功能仅用于调试目的,不应在生产服务器上使用,因为回溯可能会泄露密码或其他敏感信息。(由 Alan McIntyre 作为他在 2007 年 Google 编程之夏项目的一部分贡献。)

  • xmlrpclib 模块不再自动将 datetime.datedatetime.time 转换为 xmlrpclib.DateTime 类型;转换语义不一定适用于所有应用程序。使用 xmlrpclib 的代码应转换 datetime 实例。(bpo-1330538)该代码还可以处理 1900 年之前的日期(由 Ralf Schmitt 贡献;bpo-2014)以及 XML-RPC 响应中使用 <i8> 表示的 64 位整数(由 Riku Lindblad 贡献;bpo-2985)。

  • zipfile 模块的 ZipFile 类现在具有 extract()extractall() 方法,它们会将单个文件或存档中的所有文件解压缩到当前目录或指定目录。

    z = zipfile.ZipFile('python-251.zip')
    
    # Unpack a single file, writing it relative
    # to the /tmp directory.
    z.extract('Python/sysmodule.c', '/tmp')
    
    # Unpack all the files in the archive.
    z.extractall()
    

    (由 Alan McIntyre 贡献;bpo-467924。)

    open()read()extract() 方法现在可以接受文件名或 ZipInfo 对象。当存档意外包含重复的文件名时,这非常有用。(由 Graham Horler 贡献;bpo-1775025。)

    最后,zipfile 现在支持为存档文件使用 Unicode 文件名。(由 Alexey Borzenkov 贡献;bpo-1734346。)

ast 模块

ast 模块提供了 Python 代码的抽象语法树表示,Armin Ronacher 贡献了一组辅助函数,可以执行各种常见任务。这些函数对于 HTML 模板包、代码分析器以及处理 Python 代码的类似工具非常有用。

parse() 函数接受一个表达式并返回一个 AST。 dump() 函数输出树的表示形式,适合于调试。

import ast

t = ast.parse("""
d = {}
for i in 'abcdefghijklm':
    d[i + i] = ord(i) - ord('a') + 1
print d
""")
print ast.dump(t)

这将输出一个深度嵌套的树。

Module(body=[
  Assign(targets=[
    Name(id='d', ctx=Store())
   ], value=Dict(keys=[], values=[]))
  For(target=Name(id='i', ctx=Store()),
      iter=Str(s='abcdefghijklm'), body=[
    Assign(targets=[
      Subscript(value=
        Name(id='d', ctx=Load()),
          slice=
          Index(value=
            BinOp(left=Name(id='i', ctx=Load()), op=Add(),
             right=Name(id='i', ctx=Load()))), ctx=Store())
     ], value=
     BinOp(left=
      BinOp(left=
       Call(func=
        Name(id='ord', ctx=Load()), args=[
          Name(id='i', ctx=Load())
         ], keywords=[], starargs=None, kwargs=None),
       op=Sub(), right=Call(func=
        Name(id='ord', ctx=Load()), args=[
          Str(s='a')
         ], keywords=[], starargs=None, kwargs=None)),
       op=Add(), right=Num(n=1)))
    ], orelse=[])
   Print(dest=None, values=[
     Name(id='d', ctx=Load())
   ], nl=True)
 ])

literal_eval() 方法接受一个字符串或表示字面表达式的 AST,对其进行解析和求值,并返回结果值。字面表达式是一个 Python 表达式,仅包含字符串、数字、字典等,但不包含语句或函数调用。 如果你需要对表达式求值,但不希望承担使用 eval() 调用的安全风险,那么 literal_eval() 将安全地处理它。

>>> literal = '("a", "b", {2:4, 3:8, 1:2})'
>>> print ast.literal_eval(literal)
('a', 'b', {1: 2, 2: 4, 3: 8})
>>> print ast.literal_eval('"a" + "b"')
Traceback (most recent call last):
  ...
ValueError: malformed string

该模块还包括 NodeVisitorNodeTransformer 类,用于遍历和修改 AST,以及用于常见转换(例如更改行号)的函数。

future_builtins 模块

Python 3.0 对内置函数进行了许多更改,并且大多数更改无法在 Python 2.x 系列中引入,因为这会破坏兼容性。future_builtins 模块提供了这些内置函数的版本,可以在编写与 3.0 兼容的代码时导入。

此模块中的函数目前包括:

  • ascii(obj): 等效于 repr()。在 Python 3.0 中,repr() 将返回 Unicode 字符串,而 ascii() 将返回纯 ASCII 字节字符串。

  • filter(predicate, iterable)map(func, iterable1, ...):3.0 版本返回迭代器,而 2.x 内置函数返回列表。

  • hex(value)oct(value):这些版本将调用 __index__() 方法并将结果转换为十六进制或八进制,而不是调用 __hex__()__oct__() 方法。oct() 将使用新的 0o 表示法来表示其结果。

json 模块:JavaScript 对象表示法

新的 json 模块支持 JSON (JavaScript 对象表示法) 中 Python 类型的编码和解码。 JSON 是一种轻量级的交换格式,常用于 Web 应用程序。有关 JSON 的更多信息,请参阅 http://www.json.org

json 支持解码和编码大多数内置 Python 类型。以下示例编码和解码字典:

>>> import json
>>> data = {"spam": "foo", "parrot": 42}
>>> in_json = json.dumps(data) # Encode the data
>>> in_json
'{"parrot": 42, "spam": "foo"}'
>>> json.loads(in_json) # Decode into a Python object
{"spam": "foo", "parrot": 42}

还可以编写自己的解码器和编码器来支持更多类型。还支持 JSON 字符串的漂亮打印。

json(最初称为 simplejson)由 Bob Ippolito 编写。

plistlib 模块:属性列表解析器

.plist 格式通常在 Mac OS X 上用于存储基本数据类型(数字、字符串、列表和字典),方法是将它们序列化为基于 XML 的格式。它类似于数据类型的 XML-RPC 序列化。

尽管主要在 Mac OS X 上使用,但该格式没有任何 Mac 特有的内容,并且 Python 实现可在 Python 支持的任何平台上运行,因此 plistlib 模块已升级到标准库。

使用该模块很简单:

import sys
import plistlib
import datetime

# Create data structure
data_struct = dict(lastAccessed=datetime.datetime.now(),
                   version=1,
                   categories=('Personal','Shared','Private'))

# Create string containing XML.
plist_str = plistlib.writePlistToString(data_struct)
new_struct = plistlib.readPlistFromString(plist_str)
print data_struct
print new_struct

# Write data structure to a file and read it back.
plistlib.writePlist(data_struct, '/tmp/customizations.plist')
new_struct = plistlib.readPlist('/tmp/customizations.plist')

# read/writePlist accepts file-like objects as well as paths.
plistlib.writePlist(data_struct, sys.stdout)

ctypes 增强功能

Thomas Heller 继续维护和增强 ctypes 模块。

ctypes 现在支持表示 C99 bool 类型的 c_bool 数据类型。(由 David Remahl 贡献;bpo-1649190。)

ctypes 字符串、缓冲区和数组类型改进了对扩展切片语法的支持,其中提供了 (start, stop, step) 的各种组合。(由 Thomas Wouters 实现。)

所有 ctypes 数据类型现在都支持 from_buffer()from_buffer_copy() 方法,这些方法基于提供的缓冲区对象创建 ctypes 实例。from_buffer_copy() 复制对象的内容,而 from_buffer() 将共享同一内存区域。

一个新的调用约定告诉 ctypes 在每次包装调用开始时清除 errno 或 Win32 LastError 变量。(由 Thomas Heller 实现;bpo-1798。)

现在,你可以在函数调用后检索 Unix errno 变量。创建包装函数时,你可以将 use_errno=True 作为关键字参数提供给 DLL() 函数,然后调用模块级方法 set_errno()get_errno() 来设置和检索错误值。

Win32 LastError 变量通过 DLL()OleDLL()WinDLL() 函数类似地受支持。你将 use_last_error=True 作为关键字参数提供,然后调用模块级方法 set_last_error()get_last_error()

用于检索指向 ctypes 实例的指针的 byref() 函数现在有一个可选的 offset 参数,它是一个字节计数,将添加到返回的指针中。

改进的 SSL 支持

Bill Janssen 对 Python 2.6 的安全套接字层支持进行了大量改进,添加了一个新模块 ssl,该模块基于 OpenSSL 库构建。这个新模块提供了对协商协议、使用的 X.509 证书的更多控制,并且更好地支持在 Python 中编写 SSL 服务器(而不是客户端)。socket 模块中现有的 SSL 支持尚未删除,并且会继续工作,尽管它将在 Python 3.0 中被删除。

要使用新模块,必须首先以通常的方式创建 TCP 连接,然后将其传递给 ssl.wrap_socket() 函数。可以指定是否需要证书,并通过调用 getpeercert() 方法来获取证书信息。

另请参阅

有关 ssl 模块的文档。

弃用和删除

  • 字符串异常已被删除。尝试使用它们会引发 TypeError

  • 根据 PEP 352 的规定,对 Exception 接口的更改将继续进行。对于 2.6,message 属性已被弃用,转而使用 args 属性。

  • (3.0-警告模式) Python 3.0 将采用经过重组的标准库,其中将删除许多过时的模块并重命名其他模块。在 3.0-警告模式下运行的 Python 2.6 将在导入这些模块时发出警告。

    已弃用的模块列表为:audiodev, bgenlocations, buildtools, bundlebuilder, Canvas, compiler, dircache, dl, fpformat, gensuitemodule, ihooks, imageop, imgfile, linuxaudiodev, mhlib, mimetools, multifile, new, pure, statvfs, sunaudiodev, test.testalltoaiff

  • gopherlib 模块已被删除。

  • MimeWriter 模块和 mimify 模块已被弃用;请改用 email 包。

  • md5 模块已被弃用;请改用 hashlib 模块。

  • posixfile 模块已被弃用;fcntl.lockf() 提供了更好的锁定。

  • popen2 模块已被弃用;请使用 subprocess 模块。

  • rgbimg 模块已被删除。

  • sets 模块已被弃用;最好使用内置的 setfrozenset 类型。

  • sha 模块已被弃用;请改用 hashlib 模块。

构建和 C API 更改

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

  • (19 年后!)Python 现在必须使用 C89 编译器进行编译。这意味着 Python 源代码树已经放弃了它自己的 memmove()strerror() 实现,它们位于 C89 标准库中。

  • Python 2.6 可以使用 Microsoft Visual Studio 2008(版本 9.0)构建,这是新的默认编译器。有关构建文件,请参见 PCbuild 目录。(由 Christian Heimes 实现。)

  • 在 Mac OS X 上,Python 2.6 可以编译为 4 路通用构建。 configure 脚本可以接受 --with-universal-archs=[32-bit|64-bit|all] 开关,控制二进制文件是为 32 位架构(x86、PowerPC)、64 位(x86-64 和 PPC-64)还是两者都构建。(由 Ronald Oussoren 贡献。)

  • 在 Python 2.6.6 中添加的新函数 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()。请注意,使用此函数将破坏与 Python 版本 2.6.5 及更早版本的兼容性;如果您必须继续使用早期版本,您可以单独保留对 PySys_SetArgv() 的调用,并在之后调用 PyRun_SimpleString("sys.path.pop(0)\n") 以丢弃第一个 sys.path 组件。

    安全问题报告为 CVE 2008-5983;在 gh-50003 中进行了讨论,并由 Antoine Pitrou 修复。

  • BerkeleyDB 模块现在有一个 C API 对象,可作为 bsddb.db.api 使用。希望将 bsddb 模块用于自身目的的其他 C 扩展可以使用此对象。(由 Duncan Grisby 贡献。)

  • 先前在 PEP 3118 部分中描述的新缓冲区接口添加了 PyObject_GetBuffer()PyBuffer_Release(),以及其他一些函数。

  • Python 对 C stdio 库的使用现在是线程安全的,或者至少与底层库的线程安全性一样。如果一个线程关闭文件对象,而另一个线程正在读取或写入该对象,则会发生一个长期存在的潜在错误。在 2.6 中,文件对象具有引用计数,由 PyFile_IncUseCount()PyFile_DecUseCount() 函数操作。除非引用计数为零,否则无法关闭文件对象。在使用 FILE * 指针执行 I/O 操作之前,应在仍持有 GIL 的情况下调用 PyFile_IncUseCount(),并在重新获取 GIL 后立即调用 PyFile_DecUseCount()。(由 Antoine Pitrou 和 Gregory P. Smith 贡献。)

  • 在两个不同的线程中同时导入模块不再会导致死锁;现在它将引发 ImportError。新的 API 函数 PyImport_ImportModuleNoBlock() 将首先在 sys.modules 中查找模块,然后在获取导入锁后尝试导入它。如果导入锁由另一个线程持有,则会引发 ImportError。(由 Christian Heimes 贡献。)

  • 一些函数会返回有关平台浮点数支持的信息。PyFloat_GetMax() 返回可表示的最大浮点数值,而 PyFloat_GetMin() 返回最小的正值。PyFloat_GetInfo() 返回一个包含更多来自 float.h 文件信息的对象,例如 "mant_dig"(尾数中的位数)、"epsilon" (1.0 和下一个可表示的最大值之间的最小差值)以及其他几个值。(由 Christian Heimes 贡献;bpo-1534。)

  • 使用 PyComplex_AsCComplex() 的 C 函数和方法现在将接受具有 __complex__() 方法的参数。特别是,cmath 模块中的函数现在将接受具有此方法的对象。这是 Python 3.0 更改的反向移植。(由 Mark Dickinson 贡献;bpo-1675423。)

  • Python 的 C API 现在包含两个用于不区分大小写的字符串比较的函数,PyOS_stricmp(char*, char*)PyOS_strnicmp(char*, char*, Py_ssize_t)。(由 Christian Heimes 贡献;bpo-1635。)

  • 许多 C 扩展在 init* 函数中定义自己的小型宏,用于将整数和字符串添加到模块的字典中。Python 2.6 最终定义了用于将值添加到模块的标准宏,PyModule_AddStringMacroPyModule_AddIntMacro()。(由 Christian Heimes 贡献。)

  • 一些宏在 3.0 和 2.6 中都被重命名,以使其更清晰地表明它们是宏而不是函数。Py_Size() 变成了 Py_SIZE()Py_Type() 变成了 Py_TYPE()Py_Refcnt() 变成了 Py_REFCNT()。为了向后兼容,混合大小写的宏在 Python 2.6 中仍然可用。(bpo-1629

  • 现在,当在调试版本的 Python 上运行时,Distutils 会将其构建的 C 扩展放在不同的目录中。(由 Collin Winter 贡献;bpo-1530959。)

  • 一些基本数据类型,例如整数和字符串,维护着可以重用的对象的内部空闲列表。这些空闲列表的数据结构现在遵循命名约定:变量始终命名为 free_list,计数器始终命名为 numfree,并且始终定义一个宏 Py<typename>_MAXFREELIST

  • 一个新的 Makefile 目标 “make patchcheck” 为制作补丁准备 Python 源代码树:它修复所有已修改的 .py 文件中的尾随空格,检查文档是否已更改,并报告 Misc/ACKSMisc/NEWS 文件是否已更新。(由 Brett Cannon 贡献。)

    另一个新目标 “make profile-opt” 使用 GCC 的配置文件引导优化来编译 Python 二进制文件。它在启用分析的情况下编译 Python,运行测试套件以获取一组分析结果,然后使用这些结果进行优化编译。(由 Gregory P. Smith 贡献。)

特定于端口的更改:Windows

  • 已放弃对 Windows 95、98、ME 和 NT4 的支持。Python 2.6 至少需要 Windows 2000 SP4。

  • Windows 上的新默认编译器是 Visual Studio 2008(版本 9.0)。Visual Studio 2003(版本 7.1)和 2005(版本 8.0)的构建目录已移至 PC/ 目录。新的 PCbuild 目录支持 X64 的交叉编译、调试构建和配置文件引导优化 (PGO)。PGO 构建比普通构建快大约 10%。(由 Christian Heimes 在 Amaury Forgeot d’Arc 和 Martin von Löwis 的帮助下贡献。)

  • msvcrt 模块现在支持控制台 I/O API 的普通字符和宽字符变体。getwch() 函数读取一个按键并返回一个 Unicode 值,getwche() 函数也是如此。putwch() 函数接受一个 Unicode 字符并将其写入控制台。(由 Christian Heimes 贡献。)

  • os.path.expandvars() 现在将扩展 “%var%” 形式的环境变量,“~user” 将扩展为用户的家目录路径。(由 Josiah Carlson 贡献;bpo-957650。)

  • socket 模块的套接字对象现在具有一个 ioctl() 方法,该方法提供对 WSAIoctl() 系统接口的有限接口。

  • _winreg 模块现在有一个函数 ExpandEnvironmentStrings(),该函数扩展输入字符串中诸如 %NAME% 之类的环境变量引用。此模块提供的句柄对象现在支持上下文协议,因此它们可以在 with 语句中使用。(由 Christian Heimes 贡献。)

    _winreg 还更好地支持 x64 系统,公开了 DisableReflectionKey()EnableReflectionKey()QueryReflectionKey() 函数,这些函数启用和禁用在 64 位系统上运行的 32 位进程的注册表反射。(bpo-1753245

  • msilib 模块的 Record 对象获得了 GetInteger()GetString() 方法,这些方法将字段值作为整数或字符串返回。(由 Floris Bruynooghe 贡献;bpo-2125。)

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

  • 在编译 Python 的框架构建时,现在可以通过为 configure 脚本提供 --with-framework-name= 选项来指定要使用的框架名称。

  • macfs 模块已被删除。这反过来又导致必须删除 macostools.touched() 函数,因为它依赖于 macfs 模块。(bpo-1490190

  • 许多其他的 Mac OS 模块已被弃用,并将在 Python 3.0 中删除:_builtinSuitesaepackaetoolsaetypesapplesingleappletrawmainappletrunnerargvemulatorAudio_macautoGILCarboncfmfileCodeWarriorColorPickerEasyDialogsExplorerFinderFrameWorkfindertoolsicicglueicopenmacerrorsMacOSmacfsmacostoolsmacresourceMiniAEFrameNavNetscapeOSATerminologypimpPixMapWrapperStdSuitesSystemEventsTerminalterminalcommand

特定于端口的更改:IRIX

一些旧的 IRIX 特定模块已被弃用,并将在 Python 3.0 中删除:alALcdcddbcdplayerCLclDEVICEERRNOFILEFLflflpfmGETGLWSGLglINIOCTLjpegpanelparserreadcdSVsvtorgbvideoreaderWAIT

移植到 Python 2.6

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

  • 不应可哈希化的类应在其定义中设置 __hash__ = None 以指示该事实。

  • 字符串异常已被删除。尝试使用它们会引发 TypeError

  • collections.deque__init__() 方法现在会在从可迭代对象添加元素之前清除 deque 的任何现有内容。此更改使行为与 list.__init__() 匹配。

  • object.__init__() 之前接受任意参数和关键字参数,并忽略它们。 在 Python 2.6 中,不再允许这样做,并且会导致 TypeError。 这会影响最终调用 object 上相应方法的 __init__() 方法(可能通过使用 super())。 有关讨论,请参阅 bpo-1683368

  • 现在,Decimal 构造函数在传递字符串时接受前导和尾随空格。 以前,它会引发 InvalidOperation 异常。 另一方面,Context 对象的 create_decimal() 方法现在明确禁止额外的空格,引发 ConversionSyntax 异常。

  • 由于实现上的偶然性,如果您将文件路径传递给内置的 __import__() 函数,它实际上会导入指定的文件。 然而,这从来都不是有意为之的,现在该实现明确检查这种情况并引发 ImportError

  • C API:PyImport_Import()PyImport_ImportModule() 函数现在默认为绝对导入,而不是相对导入。 这将影响导入其他模块的 C 扩展。

  • C API:不应可哈希化的扩展数据类型应将其 tp_hash 插槽定义为 PyObject_HashNotImplemented()

  • socket 模块异常 socket.error 现在继承自 IOError。 以前它不是 StandardError 的子类,但现在它是,通过 IOError。(由 Gregory P. Smith 实现;bpo-1706815。)

  • xmlrpclib 模块不再自动将 datetime.datedatetime.time 转换为 xmlrpclib.DateTime 类型;这种转换语义对于所有应用程序来说不一定是正确的。 使用 xmlrpclib 的代码应该转换 datetime 实例。( bpo-1330538 )

  • (3.0-警告模式)当使用切片或索引访问 Exception 类时,现在会发出警告;将 Exception 表现为类似元组的行为正在逐步淘汰。

  • (3.0-警告模式)两个字典或两个未实现比较方法的对象之间的不相等比较会被报告为警告。 dict1 == dict2 仍然有效,但 dict1 < dict2 正在逐步淘汰。

    单元格之间的比较(单元格是 Python 作用域规则的实现细节)也会导致警告,因为这种比较在 3.0 中被完全禁止。

对于嵌入 Python 的应用程序

  • PySys_SetArgvEx() 函数在 Python 2.6.6 中添加,让应用程序在使用现有的 PySys_SetArgv() 函数时可以关闭一个安全漏洞。检查您是否正在调用 PySys_SetArgv(),并仔细考虑应用程序是否应该使用将 *updatepath* 设置为 false 的 PySys_SetArgvEx()

致谢

作者要感谢以下人员为本文的各种草案提供建议、更正和帮助:Georg Brandl、Steve Brown、Nick Coghlan、Ralph Corderoy、Jim Jewett、Kent Johnson、Chris Lambacher、Martin Michlmayr、Antoine Pitrou、Brian Warner。