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 语言的一次重大重新设计。 只要有可能,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 新增了一些内置函数并对部分现有内置函数的语法进行了修改。 在 3.0 中新增的函数如 bin() 已直接添加到 Python 2.6 中,但现有内置函数则未修改;替代做法是在 future_builtins 模块中包含具有 3.0 新语法的版本。 要与 3.0 兼容的代码可以在必要时执行 from future_builtins import hex, map

一个新的命令行开关 -3 可以对 Python 3.0 将移除的特性发出警告。 你可以使用该开关运行代码,以了解将代码移植到 3.0 所需的工作量。 Python 代码可以使用布尔型变量 sys.py3kwarning 访问该开关的值,C 扩展代码可以使用 Py_Py3kWarningFlag 访问该开关的值。

参见

3xxx 系列 PEP 包含针对 Python 3.0 的提议。 PEP 3000 描述了 Python 3.0 的开发进程。 从 PEP 3100 开始描述 Python 3.0 的主要目标,然后继续列出提议具体特性的更高数字的 PEP。

开发过程的变化

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

新问题追踪:简述

很长一段时间以来,Python开发人员对SourceForge的bug跟踪器越来越恼火。SourceForge的托管解决方案不允许进行大量定制;例如,无法定制问题的生命周期。

Python软件基金会的基础设施委员会因此发布了一个问题跟踪器的征集公告,邀请志愿者设置不同的产品,并从SourceForge导入一些错误和补丁。评估了四种不同的跟踪器:JiraLaunchpadRoundup <https://roundup.sourceforge.io/>`__和`Trac。委员会最终确定Jira和Roundup为两个候选方案。Jira是一个商业产品,为自由软件项目提供免费托管实例;Roundup是一个开源项目,需要志愿者来管理,并需要一个服务器来托管。

在发出志愿者号召后,在https://bugs.python.org的一个Roundup的安装可以托管多个跟踪器,现在该服务器还托管Jython和Python网站的问题跟踪器。它肯定会在未来找到其他用途。在可能的情况下,此版本的“What's New in Python”链接到每个更改的bug/补丁项。

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 编写。在 1980 年代和 1990 年代早期,大多数文档都是打印出来供日后学习的,而不是在网上查看。 LaTeX 被广泛使用,因为它既能提供美观的打印输出,又能在掌握了标记的基本规则后直接进行编写。

如今 LaTeX 仍被用于编写印刷出版物,但编程工具的格局已经发生了变化。 我们不再打印成堆的文档,取而代之的是在线浏览,HTML 已成为最重要的支持格式。 不幸的是,将 LaTeX 转换为 HTML 相当复杂,长期担任 Python 文档编辑的 Fred L. Drake Jr. 花了许多时间在维护转换过程上。 偶尔有人会建议将文档转换成 SGML,之后再转换成 XML,但进行良好的转换是一项艰巨的任务,从来没有人投入所需的时间来完成这项工作。

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

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

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

参见

Documenting 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
        ... 更多处理代码 ...

在此语句被执行之后,文件对象 f 将被自动关闭,即使是当 for 循环在代码块中间引发了异常的时候也是如此。

备注

在此情况下,f 就是由 open() 所创建的对象,因为 __enter__() 会返回 self

threading 模块的加锁和条件变量也支持 'with' 语句:

lock = threading.Lock()
with lock:
    # 关键代码段
    ...

这个锁会在代码块被执行之前锁定并总是会在代码块完成之后释放。

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

from decimal import Decimal, Context, localcontext

# 使用默认精度 28 位显示
v = Decimal('578')
print v.sqrt()

with localcontext(Context(prec=16)):
    # 此代码块中的所有代码使用 16 位精度。
    # 退出代码块时恢复原始上下文。
    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__() 方法,但 typevaluetraceback 都是 None

让我们通过一个例子来思考。我不会展示详细的代码,而只会概述支持事务的数据库所需的方法。

(对于不熟悉数据库术语的人来说:对数据库的一组更改被组合成一个事务。事务可以被提交,意味着所有更改都被写入数据库,或者被回滚,意味着所有更改都被丢弃,数据库保持不变。更多信息请参阅任何数据库教材。)

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

db_connection = DatabaseConnection()
with db_connection as cursor:
    cursor.execute('insert into ...')
    cursor.execute('delete from ...')
    # ... 更多操作 ...

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

class DatabaseConnection:
    # 数据库接口
    def cursor(self):
        "返回一个游标对象并开始一个新事务"
    def commit(self):
        "提交当前事务"
    def rollback(self):
        "回滚当前事务"

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

class DatabaseConnection:
    ...
    def __enter__(self):
        # 开始新事务的代码
        cursor = self.cursor()
        return cursor

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

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

class DatabaseConnection:
    ...
    def __exit__(self, type, value, tb):
        if tb is None:
            # 没有异常,因此提交
            self.commit()
        else:
            # 发生异常,因此回滚。
            self.rollback()
            # 返回 False

contextlib 模块

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

该装饰器名为 contextmanager(),它允许你编写单个生成器函数,而不是定义一个新的类。生成器应该生成恰好一个值。yield 之前的代码将作为 __enter__() 方法执行,生成的值将作为该方法的返回值,如果有的话,将绑定到 '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" 语句

PEP由Guido van Rossum和Nick Coghlan撰写;由Mike Bland、Guido van Rossum和Neal Norwitz实现。PEP展示了为'with'语句生成的代码,这对于学习该语句的工作原理很有帮助。

contextlib 模块的文档。

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

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

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

PEP 302风格的导入器可以按需设置 __package__。实现 -m 开关的 runpy 模块现在就这样做,因此相对导入现在可以在从包内运行的脚本中正确工作。

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 目录

PEP 由 Christian Heimes 撰写并实现。

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):
    "计算阶乘"
    # 如果 N 是 4 的倍数,这个函数将会花费更长的时间。
    if (N % 4) == 0:
        time.sleep(.05 * N/4)

    # 计算结果
    fact = 1L
    for i in range(1, N+1):
        fact = fact * i

    # 将结果放入队列
    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):
    "计算阶乘"
    # 计算结果
    fact = 1L
    for i in range(1, N+1):
        fact = fact * i

    # 将结果存储在字典中
    dictionary[N] = fact

if __name__ == '__main__':
    p = Pool(5)
    mgr = Manager()
    d = mgr.dict()         # 创建共享字典

    # 使用池运行任务
    for N in range(1, 1000, 10):
        p.apply_async(factorial, (N, d))

    # 标记池为关闭 -- 不能再添加任务。
    p.close()

    # 等待任务退出
    p.join()

    # 输出结果
    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 - 添加多任务处理包

PEP 由 Jesse Noller 和 Richard Oudkerk 撰写,由 Richard Oudkerk 和 Jesse Noller 实现。

PEP 3101: 高级字符串格式

在 Python 3.0 中,% 运算符被更强大的字符串格式化方法 format() 所补充。对 str.format() 方法的支持已经回溯到 Python 2.6。

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

>>> # 将位置参数0替换到字符串中。
>>> "User ID: {0}".format("root")
'User ID: root'
>>> # 使用命名关键字参数
>>> "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 作为键来查找值。以数字开头的字符串将被转换为整数。你不能在格式字符串内编写更复杂的表达式。

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

>>> # 字段 0:左对齐,填充至 15 个字符
>>> # 字段 1:右对齐,填充至 6 个字符
>>> 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 - 高级字符串格式

PEP 由 Eric V. Smith 撰写并实现。

PEP 3105: print 改为函数

在 Python 3.0 中 print 语句变成了 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 改为函数

PEP 由 Georg Brandl 撰写。

PEP 3110: 异常处理的变更

Python 程序员偶尔会犯的一个错误是编写这样的代码:

try:
    ...
except TypeError, ValueError:  # 错误!
    ...

作者可能试图捕获 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 中捕获异常

PEP 由 Collin Winter 撰写并实现。

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 字符

在 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 撰写, 补丁2.6 由 Christian Heimes 撰写。

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),并支持 universal newlinesTextIOBase 定义了 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 - 修改缓冲区协议

PEP 由 Travis Oliphant 和 Carl Banks 撰写,由 Travis Oliphant 实现。

PEP 3119: 抽象基类

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

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

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

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

import collections

class Storage(collections.MutableMapping):
    ...

或者,你可以不从一个期望的抽象基类派生类,而是通过调用抽象基类的 register() 方法来注册该类:

import collections

class Storage:
    ...

collections.MutableMapping.register(Storage)

对于你编写的类,从抽象基类派生可能更清晰。register() 方法在你编写了一个新的抽象基类,可以描述一个现有类型或类,或者你想声明某个第三方类实现了抽象基类时很有用。例如,如果你定义了一个 PrintableType 抽象基类,可以这样操作:

# 注册 Python 的类型
PrintableType.register(int)
PrintableType.register(float)
PrintableType.register(str)

类应该遵守抽象基类指定的语义,但 Python 无法检查这一点;这取决于类作者理解抽象基类的要求并相应地实现代码。

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

def func(d):
    if not isinstance(d, collections.MutableMapping):
        raise ValueError("期望映射对象,而不是 %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 - 引入抽象基类

PEP 由 Guido van Rossum 和 Talin 编写。由 Guido van Rossum 实现。由 Benjamin Aranguren 回退到 2.6 版本,Alex Martelli 协助。

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

Python 3.0 改变了八进制(基数为8)整数的语法,使用 "0o" 或 "0O" 作为前缀,而不是以零开头,并增加了对二进制(基数为2)整数的支持,使用 "0b" 或 "0B" 作为前缀。

Python 2.6 并没有放弃以零开头表示八进制数的支持,但增加了对 "0o" 和 "0b" 的支持:

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

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

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

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

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

参见

PEP 3127 - 整型字面量支持和语法

PEP 由 Patrick Maupin 编写;由 Eric Smith 回退到 2.6 版本。

PEP 3129: 类装饰器

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

@foo
@bar
class A:
  pass

这相当于:

class A:
  pass

A = foo(bar(A))

参见

PEP 3129 - 类装饰器

PEP 由 Collin Winter 撰写。

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

Python 3.0 增加了几种受 Scheme 数值塔启发的数值类型的抽象基类。这些类已回退到 2.6 版本,作为 numbers 模块。

最通用的 ABC 是 Number。它定义了没有任何操作,仅用于通过 isinstance(obj, Number) 检查对象是否为数字。

ComplexNumber 的子类。复数可以进行加法、减法、乘法、除法和指数运算,并且可以检索实部和虚部以及获得一个数的共轭。Python 内置的复数类型是 Complex 的实现。

Real 进一步从 Complex 派生,并添加了仅适用于实数的操作:floor()trunc(),四舍五入,取模 N 的余数,地板除法以及比较操作。

Rational 数从 Real 派生,具有 numeratordenominator 属性,并且可以转换为浮点数。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 - 数字的类型层次结构

PEP 由 Jeffrey Yasskin 撰写。

Scheme 的数值塔,来自 Guile 手册。

Scheme 的数字数据类型,来自 R5RS Scheme 规范。

fractions 模块

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

Fraction 构造函数接受两个 Integral 值,这两个值将分别是结果分数的分子和分母。

>>>  fractions 导入 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)

为了将浮点数转换为有理数,float 类型现在有一个 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,这些是装饰器,提供了向现有属性添加获取器、设置器或删除器函数的有用快捷方式。你可以像这样使用它们:

    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')  # 所有输入的交集
    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(),如果它们的浮点参数是无穷大或非数值,则返回真。(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 贡献。) 通过使用 pymalloc 为 Unicode 字符串的数据分配内存,减少了内存使用。

  • with 语句现在将 __exit__() 方法存储在堆栈上,从而产生了一小部分速度提升。(由 Jeffrey Yasskin 实现)

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

解释器改动

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

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

可以通过在运行解释器之前设置 PYTHONIOENCODING 环境变量来指定标准输入、输出和标准错误的编码。值应为形如 <编码><编码>:<错误处理器> 的字符串。编码 部分指定编码的名称,例如 utf-8latin-1;可选的 错误处理器 部分指定对无法由编码处理的字符的处理方式,应为 "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 模块现在使用最高可用的序列化协议,而不是限制自己使用协议 1。(由 W. Barnes 贡献。)

  • cgi 模块现在可以从 HTTP POST 请求的查询字符串中读取变量。这使得可以使用包含查询字符串的表单操作,例如 "/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() 返回复数的辐角(也称为角度)。

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

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

    这些修订还提高了 cmath 模块的数值稳定性。对于所有函数,结果的实部和虚部在可能的情况下都精确到几个最小精度单位(ulps)。详情请见 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')
    >>> # 名称可以用空格或逗号分隔。
    >>> # 'id, name, type, size' 也是有效的。
    >>> var_type._fields
    ('id', 'name', 'type', 'size')
    
    >>> var = var_type(1, 'frequency', 'int', 4)
    >>> print var[0], var.id    # 等效
    1 1
    >>> print var[2], var.type  # 等效
    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 属性。在某些浏览器中,设置了此属性的 cookie 不能被 JavaScript 代码访问或操作。(由 Arvin Schnell 贡献;bpo-1638033。)

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

    # 从 y=0,x=21 开始的粗体文本
    # 并影响该行的其余部分。
    stdscr.chgat(0, 21, curses.A_BOLD)
    

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

  • 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() 方法将返回一个由 sign, digitsexponent 字段组成的具名元组。

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

  • 现在 difflib 模块的 SequenceMatcher 类将返回代表匹配结果的具名元组,包含 a, bsize 等属性。 (由 Raymond Hettinger 贡献。)

  • ftplib.FTP 类构造函数以及 connect() 方法中添加了一个可选的 timeout 参数,用于指定以秒为单位的超时时间。 (由 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 贡献)

  • glob.glob() 函数现在可以在使用 Unicode 路径并在目录中匹配到 Unicode 文件名时返回 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 为真,日志文件的打开将被延迟,直到第一次调用 emit()。 (由 Vinay Sajip 贡献)

    TimedRotatingFileHandler 还有一个 utc 构造器参数。如果该参数为真,将使用 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() 函数,它接受一个名称和一组可选的参数,返回一个可调用的对象,该对象将对传递给它的任何参数调用指定的函数。例如:

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

    (由 Gregory Petrosyan 提供建议,之后由 Georg Brandl 贡献。)

    现在 attrgetter() 函数可接受带点号的名称并执行相应的属性查找:

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

    (由 Barry Warsaw 提供建议,之后由 Georg Brandl 贡献。)

  • 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 贡献。)

  • pkgutil 模块中添加了一个 get_data() 函数,它返回随安装的 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位系统上被序列化,并在64位系统上反序列化,反之亦然。不幸的是,这一变化也意味着 Python 2.6 的 Random 对象无法在早期版本的 Python 上正确反序列化。(由 Shawn Ligocki 贡献;bpo-1727780。)

    新的 triangular(low, high, mode) 函数返回遵循三角分布的随机数。返回值介于 lowhigh 之间,不包括 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() 系统调用提供了包装函数。为现有的 poll 对象添加了 modify() 方法;pollobj.modify(fd, eventmask) 接收一个文件描述符或文件对象以及一个事件掩码,修改该文件的记录事件掩码。(由 Christian Heimes 贡献;bpo-1657。)

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

    模块 shutil 还提供了一个 ignore_patterns() 函数,用于与这个新参数一起使用。ignore_patterns() 接收任意数量的 glob-style 模式,并返回一个可调用对象,该对象将忽略匹配这些模式中的任何一个的文件和目录。以下示例复制一个目录树,但跳过 .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 中贡献。)

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

    还添加了 setitimer()getitimer() 函数(在可用的情况下)。setitimer() 允许设置间隔定时器,该定时器将在指定时间后向进程发送信号,时间测量可以是墙钟时间、消耗的进程时间或进程+系统时间之和。(由 Guilherme Polo 贡献;bpo-2240。)

  • smtplib 模块现在支持通过 SSL 的 SMTP,这得益于 SMTP_SSL 类的添加。这个类支持与现有 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-742598, bpo-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 文件。如果该变量为真,则不写入编译文件。该变量在启动时通过向 Python 解释器提供 -B 开关或通过在运行解释器之前设置 PYTHONDONTWRITEBYTECODE 环境变量来初始设置。Python 代码随后可以更改此变量的值,以控制是否写入字节码文件。(由 Neal Norwitz 和 Georg Brandl 贡献。)

    通过读取名为 sys.flags 的命名元组的属性,可以获取提供给 Python 解释器的命令行参数信息。例如,如果 Python 以详细模式执行,则 verbose 属性为真,debug 在调试模式下为真,等等。这些属性都是只读的。(由 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")
        # ... 触发警告的代码 ...
        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。)

    模块 threadingThread 对象获得了一个 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 的一部分添加,该问题重新实现了 warnings 模块的C代码部分。)

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

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

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

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

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

    z = zipfile.ZipFile('python-251.zip')
    
    # 解压单个文件,将其写入
    # 相对于 /tmp 目录。
    z.extract('Python/sysmodule.c', '/tmp')
    
    # 解压存档中的所有文件。
    z.extractall()
    

    (由 Alan McIntyre 在 bpo-467924 中贡献。)

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

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

ast 模块

ast 模块提供了 Python 代码的抽象语法树(Abstract Syntax Tree)表示,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 Object Notation

新的 json 模块支持将 Python 类型编码和解码为 JSON(JavaScript Object Notation)。 JSON 是一种轻量级的数据交换格式,常用于 Web 应用程序。 有关 JSON 的更多信息,请参见 http://www.json.org

json 模块支持对大多数内置 Python 类型进行解码和编码。 以下示例展示了如何编码和解码一个字典:

>>> import json
>>> data = {"spam": "foo", "parrot": 42}
>>> in_json = json.dumps(data) # 编码数据
>>> in_json
'{"parrot": 42, "spam": "foo"}'
>>> json.loads(in_json) # 解码到一个 Python 对象
{"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

# 创建数据结构
data_struct = dict(lastAccessed=datetime.datetime.now(),
                   version=1,
                   categories=('Personal','Shared','Private'))

# 创建包含 XML 的字符串。
plist_str = plistlib.writePlistToString(data_struct)
new_struct = plistlib.readPlistFromString(plist_str)
print data_struct
print new_struct

# 将数据结构写入文件并重新读取。
plistlib.writePlist(data_struct, '/tmp/customizations.plist')
new_struct = plistlib.readPlist('/tmp/customizations.plist')

# read/writePlist 接受文件类对象以及路径。
plistlib.writePlist(data_struct, sys.stdout)

ctypes 增强

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

ctypes 现在支持 c_bool 数据类型,它表示 C99 的 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()

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

改进的 SSL 支持

Bill Janssen 对 Python 2.6 的安全套接字层(SSL)支持进行了大量改进,通过添加一个新的模块 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将在导入这些模块时发出警告。

    已弃用的模块列表如下:audiodevbgenlocationsbuildtoolsbundlebuilderCanvascompilerdircachedlfpformatgensuitemoduleihooksimageopimgfilelinuxaudiodevmhlibmimetoolsmultifilenewpurestatvfssunaudiodevtest.testalltoaiff

  • gopherlib 模块已被移除。

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

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

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

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

  • rgbimg 模块已被移除。

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

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

构建和 C API 的变更

针对 Python 构建过程和 C API 的变更包括:

  • Python现在必须使用C89编译器进行编译(19年后!)。这意味着Python源代码树已删除其自身的 memmove()strerror() 实现,这些功能在C89标准库中。

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

  • 在Mac OS X上,Python 2.6可以编译为四路通用构建。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 标准输入输出库的使用现在是线程安全的,或者至少与底层库一样线程安全。一个长期存在的潜在错误是,如果一个线程在另一个线程正在读取或写入文件对象时关闭该文件对象。在 2.6 版本中,文件对象具有引用计数,由 PyFile_IncUseCount()PyFile_DecUseCount() 函数操作。文件对象只有在引用计数为零时才能被关闭。PyFile_IncUseCount() 应在仍持有 GIL 时调用,在进行使用 FILE * 指针的 I/O 操作之前,而 PyFile_DecUseCount() 应在重新获取 GIL 后立即调用。(由 Antoine Pitrou 和 Gregory P. Smith 贡献。)

  • Importing modules simultaneously in two different threads no longer deadlocks; it will now raise an ImportError. A new API function, PyImport_ImportModuleNoBlock(), will look for a module in sys.modules first, then try to import it after acquiring an import lock. If the import lock is held by another thread, an ImportError is raised. (Contributed by 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)

  • Distutils 在运行调试版本的 Python 时,现在将构建的 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贡献;:issue:`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中移除:alALcdcddbcdplayerCLclDEVICEERRNOFILEFLflflpfmGETGLWSGLglINIOCTLjpegpanelparserreadcdSVsvtorgbvideoreader,以及 WAIT

移植到Python 2.6

本节列出了先前描述的改变以及可能需要修改你的代码的其他问题修正:

  • 预期为不可哈希的类应当在其定义中设置 __hash__ = None 来指明这一点。

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

  • collections.deque__init__() 方法现在会在从可迭代对象添加元素之前清空deque中的任何现有内容。这一改变使得其行为与 list.__init__() 相匹配。

  • 以前 object.__init__() 接受任意参数和关键字参数,并忽略它们。在Python 2.6中,这不再被允许,并将导致 TypeError。这将影响最终调用 object 上相应方法(可能通过使用 super())的 __init__() 方法。参见 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的应用程序:

  • Python 2.6.6 中增加了 PySys_SetArgvEx() 函数,这让应用可以弥补一个在使用现有 PySys_SetArgv() 函数时会存在的安全漏洞。 请检查你是否有调用 PySys_SetArgv() 并仔细考虑应用是否应当改用 PySys_SetArgvEx() 并将 updatepath 设为假值。

致谢

作者感谢以下人员对本文各种草稿给予的建议,更正和协助: Georg Brandl、Steve Brown、Nick Coghlan、Ralph Corderoy、Jim Jewett、Kent Johnson、Chris Lambacher、 Martin Michlmayr、Antoine Pitrou、Brian Warner。