Python 3.2 有什麼新功能
***********************

作者:
   Raymond Hettinger

This article explains the new features in Python 3.2 as compared to
3.1. Python 3.2 was released on February 20, 2011. It focuses on a few
highlights and gives a few examples.  For full details, see the
Misc/NEWS file.

也參考: **PEP 392** - Python 3.2 发布计划


PEP 384: 定义稳定的ABI
======================

过去，为一个 Python 版本所构建的扩展模块通常无法用于其他 Python 版本。
特别是在 Windows 上，每一个 Python 新特性发布版都必须重新构建想要使用
的所有扩展模块。 之所以有这样的要求是因为扩展模块可以任意访问 Python
解释器的内部对象。

在 Python 3.2 中，则有了一种替代方式：扩展模块将自己约束于一个受限 API
（通过定义 Py_LIMITED_API）因而不能使用许多内部对象，仅限使用一组承诺
会在多个发布版中保持稳定的 API 函数。 作为其结果，在这种模式下为 3.2
构建的扩展模块也将能在 3.3、3.4 等版本中运行。 使用了内存结构体细节数
据的扩展模块仍然可以被构建，但将需要为每个新特性发布版重新编译。

也參考:

  **PEP 384** - 定义稳定的ABI
     由 Martin von Löwis 撰寫 PEP。


PEP 389: Argparse 命令行解析模块
================================

引入了一个新的 "argparse" 模块用于命令行解析，以克服 "optparse" 的局限
性，后者不支持位置参数（不仅仅是选项）、子命令、必需选项以及其他常见的
选项指定和验证模式。

该模块作为一个第三方模块已在社区中取得了广泛的成功。相比其前身，
"argparse" 模块功能更加全面，现在是处理命令行的首选模块。出于对大量依
赖该模块的遗留代码的考虑，旧模块仍被保留使用。

以下是一个带注释的示例解析器，展示了诸如限制结果到一组选项、在帮助屏幕
中指定 *metavar*、验证一个或多个位置参数是否存在以及创建一个必需选项等
功能：

   import argparse
   parser = argparse.ArgumentParser(
               description = 'Manage servers',         # main description for help
               epilog = 'Tested on Solaris and Linux') # displayed after help
   parser.add_argument('action',                       # argument name
               choices = ['deploy', 'start', 'stop'],  # three allowed values
               help = 'action on each target')         # help msg
   parser.add_argument('targets',
               metavar = 'HOSTNAME',                   # var name used in help msg
               nargs = '+',                            # require one or more targets
               help = 'url for target machines')       # help msg explanation
   parser.add_argument('-u', '--user',                 # -u or --user option
               required = True,                        # make it a required argument
               help = 'login as user')

在命令字符串中调用解析器的示例:

   >>> cmd = 'deploy sneezy.example.com sleepy.example.com -u skycaptain'
   >>> result = parser.parse_args(cmd.split())
   >>> result.action
   'deploy'
   >>> result.targets
   ['sneezy.example.com', 'sleepy.example.com']
   >>> result.user
   'skycaptain'

解释器自动生成的帮助示例:

   >>> parser.parse_args('-h'.split())

   usage: manage_cloud.py [-h] -u USER
                          {deploy,start,stop} HOSTNAME [HOSTNAME ...]

   Manage servers

   positional arguments:
     {deploy,start,stop}   action on each target
     HOSTNAME              url for target machines

   optional arguments:
     -h, --help            show this help message and exit
     -u USER, --user USER  login as user

   Tested on Solaris and Linux

一个非常好的 "argparse" 特性是可以定义子解析器，每个子解析器拥有它们自
己的参数模式和帮助显示:

   import argparse
   parser = argparse.ArgumentParser(prog='HELM')
   subparsers = parser.add_subparsers()

   parser_l = subparsers.add_parser('launch', help='Launch Control')   # first subgroup
   parser_l.add_argument('-m', '--missiles', action='store_true')
   parser_l.add_argument('-t', '--torpedos', action='store_true')

   parser_m = subparsers.add_parser('move', help='Move Vessel',        # second subgroup
                                    aliases=('steer', 'turn'))         # equivalent names
   parser_m.add_argument('-c', '--course', type=int, required=True)
   parser_m.add_argument('-s', '--speed', type=int, default=0)

   $ ./helm.py --help                         # top level help (launch and move)
   $ ./helm.py launch --help                  # help for launch options
   $ ./helm.py launch --missiles              # set missiles=True and torpedos=False
   $ ./helm.py steer --course 180 --speed 5   # set movement parameters

也參考:

  **PEP 389** - 新的命令行解析模块
     由 Steven Bethard 撰寫 PEP。

  参阅 升级 optparse 代码 了解与 "optparse" 的差异的细节。


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

The "logging" module provided two kinds of configuration, one style
with function calls for each option or another style driven by an
external file saved in a "ConfigParser" format.  Those options did not
provide the flexibility to create configurations from JSON or YAML
files, nor did they support incremental configuration, which is needed
for specifying logger options from a command line.

为了支持更灵活的配置方式，该模块现在提供了
"logging.config.dictConfig()"，用于通过普通的 Python 字典指定日志配置
。配置选项包括格式化器、处理器、过滤器和日志记录器。以下是一个配置字典
的工作示例：

   {"version": 1,
    "formatters": {"brief": {"format": "%(levelname)-8s: %(name)-15s: %(message)s"},
                   "full": {"format": "%(asctime)s %(name)-15s %(levelname)-8s %(message)s"}
                   },
    "handlers": {"console": {
                      "class": "logging.StreamHandler",
                      "formatter": "brief",
                      "level": "INFO",
                      "stream": "ext://sys.stdout"},
                 "console_priority": {
                      "class": "logging.StreamHandler",
                      "formatter": "full",
                      "level": "ERROR",
                      "stream": "ext://sys.stderr"}
                 },
    "root": {"level": "DEBUG", "handlers": ["console", "console_priority"]}}

如果将该字典存储在一个名为 "conf.json" 的文件中，可以使用如下代码加载
并调用它：

   >>> import json, logging.config
   >>> with open('conf.json') as f:
   ...     conf = json.load(f)
   ...
   >>> logging.config.dictConfig(conf)
   >>> logging.info("Transaction completed normally")
   INFO    : root           : Transaction completed normally
   >>> logging.critical("Abnormal termination")
   2011-02-17 11:14:36,694 root            CRITICAL Abnormal termination

也參考:

  **PEP 391** - 基于字典的日志配置
     由 Vinay Sajip 撰寫 PEP。


PEP 3148:  "concurrent.futures" 模块
====================================

用于创建和管理并发性的代码正在被收集到一个新的顶级命名空间
*concurrent* 中。其第一个成员是一个 *futures* 包，该包提供了一个统一的
高级接口，用于管理线程和进程。

"concurrent.futures" 的设计灵感来自 *java.util.concurrent* 包。在该模
型中，一个正在运行的调用及其结果由一个 "Future" 对象表示，该对象抽象了
线程、进程和远程过程调用共有的特性。该对象支持状态检查（运行中或已完成
）、超时、取消、添加回调以及访问结果或异常。

新模块的核心功能是提供了一对执行器类，用于启动和管理调用任务。这些执行
器的设计目标是简化现有并行调用工具的使用流程，它们能够帮助开发者省去以
下繁琐操作：配置资源池、发起调用任务、创建结果队列、添加超时处理机制，
以及限制线程、进程或远程过程调用的总数量。

理想情况下，每个应用程序应该在多个组件之间共享单个执行器，以便可以集中
管理进程和线程限制。这解决了当每个组件都有自己的资源管理竞争策略时出现
的设计挑战。

这两个类共享一个通用接口，包含三个方法："submit()" 用于调度可调用对象
并返回一个 "Future" 对象；"map()" 用于一次性调度多个异步调用；
"shutdown()" 用于释放资源。该类是一个 *上下文管理器*，可以在 "with" 语
句中使用，以确保在当前挂起的futures对象执行完毕时自动释放资源。

"ThreadPoolExecutor" 的一个简单示例是启动四个并行线程来复制文件：

   import concurrent.futures, shutil
   with concurrent.futures.ThreadPoolExecutor(max_workers=4) as e:
       e.submit(shutil.copy, 'src1.txt', 'dest1.txt')
       e.submit(shutil.copy, 'src2.txt', 'dest2.txt')
       e.submit(shutil.copy, 'src3.txt', 'dest3.txt')
       e.submit(shutil.copy, 'src3.txt', 'dest4.txt')

也參考:

  **PEP 3148** -- futures - 异步执行指令
     由 Brian Quinlan 撰寫 PEP。

  使用线程并行 URL 读取的代码示例，展示了如何利用线程并发获取多个网页
  内容。

  并行计算质数的代码示例，展示了 "ProcessPoolExecutor" 的用法。


PEP 3147:  PYC 仓库目录
=======================

Python 在 *.pyc* 文件中缓存字节码的方案在存在多个 Python 解释器的环境
中效果不佳。如果一个解释器遇到了由另一个解释器创建的缓存文件，它会重新
编译源代码并覆盖缓存文件，从而失去缓存的优势。

随着 Linux 发行版普遍附带多个 Python 版本，“pyc 冲突”问题变得更加突出
。这些冲突在使用 CPython 的替代品（如 Unladen Swallow）时也会出现。

为解决此问题，Python 的导入机制已进行扩展，会为每个解释器使用不同的文
件名。Python 3.2、Python 3.3 和 Unladen Swallow 不再争抢同一个名为
"mymodule.pyc" 的文件，而是分别查找 "mymodule.cpython-32.pyc"、
"mymodule.cpython-33.pyc" 和 "mymodule.unladen10.pyc"。此外，为避免这
些新文件使源目录变得杂乱，*pyc* 文件现在会被收集到一个名为
"__pycache__" 的目录中，该目录存放在包目录下。

除了文件名和目标目录之外，新方案还有几个方面是程序员可见的：

* Imported modules now have a "__cached__" attribute which stores the
  name of the actual file that was imported:

  >>> import collections
  >>> collections.__cached__ 
  'c:/py32/lib/__pycache__/collections.cpython-32.pyc'

* 针对每个解释器的唯一标签可以从 "imp" 模块访问:

  >>> import imp
  >>> imp.get_tag() 
  'cpython-32'

* Scripts that try to deduce source filename from the imported file
  now need to be smarter.  It is no longer sufficient to simply strip
  the "c" from a ".pyc" filename.  Instead, use the new functions in
  the "imp" module:

  >>> imp.source_from_cache('c:/py32/lib/__pycache__/collections.cpython-32.pyc')
  'c:/py32/lib/collections.py'
  >>> imp.cache_from_source('c:/py32/lib/collections.py') 
  'c:/py32/lib/__pycache__/collections.cpython-32.pyc'

* "py_compile" 和 "compileall" 模块已更新以反映新的命名约定和目标目录
  。*compileall* 的命令行调用有了新选项："-i" 用于指定要编译的文件和目
  录列表，"-b" 使字节码文件写入其传统位置而非 *__pycache__*。

* The "importlib.abc" module has been updated with new *abstract base
  classes* for loading bytecode files.  The obsolete ABCs, "PyLoader"
  and "PyPycLoader", have been deprecated (instructions on how to stay
  Python 3.1 compatible are included with the documentation).

也參考:

  **PEP 3147** - PYC 仓库目录
     由 Barry Warsaw 撰寫 PEP。


PEP 3149: 带有 ABI 版本标签的 .so 文件
======================================

PYC存储库目录允许多个字节码缓存文件共存。此PEP通过为共享对象文件提供一
个公共目录并为每个版本提供不同的名称，实现了类似的机制。

通用目录为 "pyshared"，文件名通过识别 Python 实现方式（如 CPython、
PyPy、Jython 等）、主版本号和次版本号以及可选的构建标志（如 "d" 表示调
试、"m" 表示 pymalloc、"u" 表示宽Unicode）来区分。对于任意包 "foo"，当
分发包安装时，您可能会看到这些文件：

   /usr/share/pyshared/foo.cpython-32m.so
   /usr/share/pyshared/foo.cpython-33md.so

对于 Python 本身，可以通过 "sysconfig" 模块中的函数来访问这些标签:

   >>> import sysconfig
   >>> sysconfig.get_config_var('SOABI')       # find the version tag
   'cpython-32mu'
   >>> sysconfig.get_config_var('EXT_SUFFIX')  # find the full filename extension
   '.cpython-32mu.so'

也參考:

  **PEP 3149** - 带有 ABI 版本标签的 .so 文件
     由 Barry Warsaw 撰寫 PEP。


PEP 3333: Python Web服务器网关接口v1.0.1
========================================

本信息性 PEP 阐明了 WSGI 协议如何处理字节/文本问题。挑战在于，尽管
HTTP 协议本身是基于字节的，但 Python 3 中的字符串处理最方便的方式是使
用 "str" 类型。

该 PEP 规范区分了用于请求/响应头和元数据的所谓 *原生字符串* (native
strings)，与用于请求和响应正文的 *字节字符串* (byte strings)。

The *native strings* are always of type "str" but are restricted to
code points between *U+0000* through *U+00FF* which are translatable
to bytes using *Latin-1* encoding.  These strings are used for the
keys and values in the environment dictionary and for response headers
and statuses in the "start_response()" function.  They must follow
**RFC 2616** with respect to encoding. That is, they must either be
*ISO-8859-1* characters or use **RFC 2047** MIME encoding.

对于从 Python 2 迁移 WSGI 应用程序的开发者，以下是关键点：

* 如果应用程序在 Python 2 中已经使用字符串作为请求/响应头，则无需更改
  。

* 如果应用程序对输出头进行编码或对输入头进行解码，则头需要重新编码为
  Latin-1。例如，一个使用 utf-8 编码的输出头原本使用
  "h.encode('utf-8')"，现在需要转换为字节到原生字符串，使用
  "h.encode('utf-8').decode('latin-1')"。

* Values yielded by an application or sent using the "write()" method
  must be byte strings.  The "start_response()" function and environ
  must use native strings.  The two cannot be mixed.

For server implementers writing CGI-to-WSGI pathways or other CGI-
style protocols, the users must to be able access the environment
using native strings even though the underlying platform may have a
different convention.  To bridge this gap, the "wsgiref" module has a
new function, "wsgiref.handlers.read_environ()" for transcoding CGI
variables from "os.environ" into native strings and returning a new
dictionary.

也參考:

  **PEP 3333** - Python Web服务器网关接口v1.0.1
     由 Phillip Eby 撰寫 PEP。


其他语言特性修改
================

对Python 语言核心进行的小改动：

* "format()" 函数和 "str.format()" 方法的字符串格式化功能为格式字符
  **#** 新增了能力。此前，对于二进制、八进制或十六进制的整数，该字符会
  使输出分别带有 '0b'、'0o' 或 '0x' 前缀。现在，它还能处理浮点数、复数
  和 Decimal 类型，确保输出始终包含小数点——即使后续没有数字跟随。

  >>> format(20, '#o')
  '0o24'
  >>> format(12.34, '#5.0f')
  '  12.'

  （由 Mark Dickinson 建议，Eric Smith 在 bpo-7094 中实现。）

* 还有一个新的 "str.format_map()" 方法，它通过接受任意的 *mapping* 对
  象，扩展了现有 "str.format()" 方法的功能。这个新方法使得可以使用字符
  串格式化与Python的许多字典类对象，如 "defaultdict"、"Shelf"、
  "ConfigParser" 或 "dbm"。它也适用于在查找前标准化键的自定义 "dict"
  子类，或者为未知键提供 "__missing__()" 方法的自定义类:

     >>> import shelve
     >>> d = shelve.open('tmp.shl')
     >>> 'The {project_name} status is {status} as of {date}'.format_map(d)
     'The testing project status is green as of February 15, 2011'

     >>> class LowerCasedDict(dict):
     ...     def __getitem__(self, key):
     ...         return dict.__getitem__(self, key.lower())
     >>> lcd = LowerCasedDict(part='widgets', quantity=10)
     >>> 'There are {QUANTITY} {Part} in stock'.format_map(lcd)
     'There are 10 widgets in stock'

     >>> class PlaceholderDict(dict):
     ...     def __missing__(self, key):
     ...         return '<{}>'.format(key)
     >>> 'Hello {name}, welcome to {location}'.format_map(PlaceholderDict())
     'Hello <name>, welcome to <location>'

   （由 Raymond Hettinger 提议并由 Eric Smith 在 bpo-6081 中贡献。）

* The interpreter can now be started with a quiet option, "-q", to
  prevent the copyright and version information from being displayed
  in the interactive mode.  The option can be introspected using the
  "sys.flags" attribute:

     $ python -q
     >>> sys.flags
     sys.flags(debug=0, division_warning=0, inspect=0, interactive=0,
     optimize=0, dont_write_bytecode=0, no_user_site=0, no_site=0,
     ignore_environment=0, verbose=0, bytes_warning=0, quiet=1)

  （由 Marcin Wojdyr 在 bpo-1772833 中贡献。）

* The "hasattr()" function works by calling "getattr()" and detecting
  whether an exception is raised.  This technique allows it to detect
  methods created dynamically by "__getattr__()" or
  "__getattribute__()" which would otherwise be absent from the class
  dictionary.  Formerly, *hasattr* would catch any exception, possibly
  masking genuine errors.  Now, *hasattr* has been tightened to only
  catch "AttributeError" and let other exceptions pass through:

     >>> class A:
     ...     @property
     ...     def f(self):
     ...         return 1 // 0
     ...
     >>> a = A()
     >>> hasattr(a, 'f')
     Traceback (most recent call last):
       ...
     ZeroDivisionError: integer division or modulo by zero

  （由 Yury Selivanov 发现并由 Benjamin Peterson 修正；bpo-9666。）

* 浮点数或复数的 "str()" 现在与它的 "repr()" 相同。以前，"str()" 形式
  更短，但这只会造成混淆，因此现在默认显示最短的 "repr()":

  >>> import math
  >>> repr(math.pi)
  '3.141592653589793'
  >>> str(math.pi)
  '3.141592653589793'

  （由 Mark Dickinson 提议并实现；bpo-9337。）

* "memoryview" objects now have a "release()" method and they also now
  support the context management protocol.  This allows timely release
  of any resources that were acquired when requesting a buffer from
  the original object.

  >>> with memoryview(b'abcdefgh') as v:
  ...     print(v.tolist())
  [97, 98, 99, 100, 101, 102, 103, 104]

  （由 Antoine Pitrou 添加；bpo-9757。）

* 此前，如果名称在嵌套块中作为自由变量出现，删除局部命名空间中的名称是
  非法的:

     def outer(x):
         def inner():
             return x
         inner()
         del x

  现在允许这样做。请记住，"except" 子句的目标是被清除的，所以这段代码
  在 Python 2.6 中可以工作，但在 Python 3.1 中会引发 "SyntaxError"，现
  在又再次可以工作:

     def f():
         def print_error():
             print(e)
         try:
             something
         except Exception as e:
             print_error()
             # implicit "del e" here

  （請見 bpo-4617。）

* The internal "structsequence" tool now creates subclasses of tuple.
  This means that C structures like those returned by "os.stat()",
  "time.gmtime()", and "sys.version_info" now work like a *named
  tuple* and now work with functions and methods that expect a tuple
  as an argument.  This is a big step forward in making the C
  structures as flexible as their pure Python counterparts:

  >>> import sys
  >>> isinstance(sys.version_info, tuple)
  True
  >>> 'Version %d.%d.%d %s(%d)' % sys.version_info 
  'Version 3.2.0 final(0)'

  （由 Arfrever Frehtes Taifersar Arahesis 建议，Benjamin Peterson 在
  bpo-8413 中实现。）

* 现在可以使用 "PYTHONWARNINGS" 环境变量来更轻松地控制警告，作为在命令
  行中使用 "-W" 的替代方案:

     $ export PYTHONWARNINGS='ignore::RuntimeWarning::,once::UnicodeWarning::'

  （由Barry Warsaw建议，Philip Jenvey在 bpo-7301 中实现。）

* 新增了一个警告类别: "ResourceWarning"。当检测到资源消耗或清理的潜在
  问题时会发出此警告。在正常发布版本中，该警告默认被禁用，但可以通过
  "warnings" 模块提供的方式或通过命令行启用。

  A "ResourceWarning" is issued at interpreter shutdown if the
  "gc.garbage" list isn't empty, and if "gc.DEBUG_UNCOLLECTABLE" is
  set, all uncollectable objects are printed.  This is meant to make
  the programmer aware that their code contains object finalization
  issues.

  当一个 *文件对象* 在没有显式关闭的情况下被销毁时，也会发出
  "ResourceWarning"。尽管此类对象的析构函数确保关闭底层的操作系统资源
  （通常是文件描述符），但对象释放的延迟可能导致各种问题，特别是在
  Windows 系统下。以下是通过命令行启用该警告的示例：

     $ python -q -Wdefault
     >>> f = open("foo", "wb")
     >>> del f
     __main__:1: ResourceWarning: unclosed file <_io.BufferedWriter name='foo'>

  （由 Antoine Pitrou 和 Georg Brandl 在 bpo-10093 和 bpo-477863 中添
  加。）

* "range" objects now support *index* and *count* methods. This is
  part of an effort to make more objects fully implement the
  "collections.Sequence" *abstract base class*.  As a result, the
  language will have a more uniform API.  In addition, "range" objects
  now support slicing and negative indices, even with values larger
  than "sys.maxsize".  This makes *range* more interoperable with
  lists:

     >>> range(0, 100, 2).count(10)
     1
     >>> range(0, 100, 2).index(10)
     5
     >>> range(0, 100, 2)[5]
     10
     >>> range(0, 100, 2)[0:5]
     range(0, 10, 2)

  （由 Daniel Stutzbach 在 bpo-9213 中贡献，由 Alexander Belopolsky 在
  bpo-2690 中贡献，由 Nick Coghlan 在 bpo-10889 中贡献。）

* "callable()" 内置函数从 Py2.x 中恢复。它提供了一个简洁、可读的替代方
  案，用于在类似 "isinstance(x, collections.Callable)" 的表达式中使用
  *抽象基类*：

  >>> callable(max)
  True
  >>> callable(20)
  False

  （請見 bpo-10518。）

* Python 的导入机制现在可以加载路径名中包含非 ASCII 字符的目录中安装的
  模块。这解决了一个令人烦恼的问题，即用户主目录中包含非 ASCII 字符的
  用户名。

   （需要 Victor Stinner 在 bpo-9425 中做大量工作。）


新增，改进和弃用的模块
======================

Python 标准库经过了大量的维护工作和质量改进。

The biggest news for Python 3.2 is that the "email" package, "mailbox"
module, and "nntplib" modules now work correctly with the bytes/text
model in Python 3.  For the first time, there is correct handling of
messages with mixed encodings.

在整个标准库中，对编码和文本与字节问题的关注更加细致。特别是，与操作系
统的交互现在能够更好地使用 Windows MBCS 编码、区域感知编码或 UTF-8 交
换非 ASCII 数据。

另一个重要的改进是大幅提升了 *SSL* 连接和安全证书的支持。

此外，更多的类现在实现了 *上下文管理器*，以支持使用 "with" 语句进行方
便且可靠的资源清理。


email
-----

Python 3 中 "email" 包的可用性已基本由 R. David Murray 的极大努力修复
。问题在于电子邮件通常以 "bytes" 而不是 "str" 文本的形式读取和存储，并
且单个电子邮件中可能包含多种编码。因此，必须扩展电子邮件包以解析和生成
字节格式的电子邮件消息。

* 新函数 "message_from_bytes()" 和 "message_from_binary_file()"，以及
  新类 "BytesFeedParser" 和 "BytesParser" 允许将二进制消息数据解析为模
  型对象。

* 给定模型的字节输入，"get_payload()" 默认将解码具有 *Content-
  Transfer-Encoding* 为 *8bit* 的消息正文，使用 MIME 头中指定的字符集
  ，并返回结果字符串。

* 给定模型的字节输入，"Generator" 将把具有 *Content-Transfer-Encoding*
  为 *8bit* 的消息正文转换为具有 *7bit* 的 *Content-Transfer-Encoding*
  。

  包含未编码的非 ASCII 字节的邮件头，将被视为使用 *unknown-8bit* 字符
  集按照 **RFC 2047** 标准进行编码。

* 一个新的类 "BytesGenerator" 生成字节输出，保留输入中未更改的任何非
  ASCII 数据，包括具有 *Content-Transfer-Encoding* 为 *8bit* 的消息正
  文。

* "smtplib" 的 "SMTP" 类现在接受字节字符串作为 "sendmail()" 方法的
  *msg* 参数，并且一个新的方法 "send_message()" 接受一个 "Message" 对
  象，并可以可选地从对象中直接获取 *from_addr* 和 *to_addrs* 地址。

（由 R. David Murray 在 bpo-4661 和 bpo-10321 中提议并实现。）


elementtree
-----------

"xml.etree.ElementTree" 包及其对应的 "xml.etree.cElementTree" 已更新至
1.3 版。

新增了几个有用的函数和方法：

* "xml.etree.ElementTree.fromstringlist()" 可根据一系列片段生成 XML 文
  档

* "xml.etree.ElementTree.register_namespace()" 用于注册全局命名空间前
  缀

* "xml.etree.ElementTree.tostringlist()" 用于字符串表示包括所有子列表

* "xml.etree.ElementTree.Element.extend()" 用于添加包含零个或多个元素
  的序列

* "xml.etree.ElementTree.Element.iterfind()" 可搜索元素和子元素

* "xml.etree.ElementTree.Element.itertext()" 创建一个包含指定元素及其
  子元素的文本迭代器。

* "xml.etree.ElementTree.TreeBuilder.end()" 关闭当前元素

* "xml.etree.ElementTree.TreeBuilder.doctype()" 处理 doctype 声明

两个方法被弃用：

* "xml.etree.ElementTree.getchildren()" 被 "list(elem)" 替代。

* "xml.etree.ElementTree.getiterator()" 被 "Element.iter" 替代。

有关更新的详细信息，请参阅 Fredrik Lundh 网站上的 Introducing
ElementTree。

（由 Florent Xicluna 和 Fredrik Lundh 在 bpo-6472 中贡献。）


functools
---------

* "functools" 模块包含一个新的装饰器用于缓存函数调用。
  "functools.lru_cache()" 可以在预期结果相同的情况下，保存对外部资源的
  重复查询。

  例如，向数据库查询函数添加缓存装饰器可以节省热门搜索的数据库访问：

  >>> import functools
  >>> @functools.lru_cache(maxsize=300)
  ... def get_phone_number(name):
  ...     c = conn.cursor()
  ...     c.execute('SELECT phonenumber FROM phonelist WHERE name=?', (name,))
  ...     return c.fetchone()[0]

  >>> for name in user_requests:        
  ...     get_phone_number(name)        # cached lookup

  为了帮助选择有效的缓存大小，包装函数被用于跟踪缓存统计信息：

  >>> get_phone_number.cache_info()     
  CacheInfo(hits=4805, misses=980, maxsize=300, currsize=300)

  如果 phonelist 表被更新，过时的缓存内容可以通过以下方式清除：

  >>> get_phone_number.cache_clear()

  (Contributed by Raymond Hettinger and incorporating design ideas
  from Jim Baker, Miki Tebeka, and Nick Coghlan; see recipe 498245,
  recipe 577479, bpo-10586, and bpo-10593.)

* The "functools.wraps()" decorator now adds a "__wrapped__" attribute
  pointing to the original callable function.  This allows wrapped
  functions to be introspected.  It also copies "__annotations__" if
  defined.  And now it also gracefully skips over missing attributes
  such as "__doc__" which might not be defined for the wrapped
  callable.

  在上面的例子中，可以通过恢复原始函数来移除缓存：

  >>> get_phone_number = get_phone_number.__wrapped__    # uncached function

  （由 Nick Coghlan 和 Terrence Cole 在 bpo-9567, bpo-3445 和 bpo-8814
  中贡献。)

* 为帮助编写具有丰富比较方法的类，新增的装饰器
  "functools.total_ordering()" 将使用现有的相等和不相等方法来填充其余
  的方法。

  例如，提供 *__eq__* and *__lt__* 将启用 "total_ordering()" 来填充
  *__le__*, *__gt__* 和 *__ge__*:

     @total_ordering
     class Student:
         def __eq__(self, other):
             return ((self.lastname.lower(), self.firstname.lower()) ==
                     (other.lastname.lower(), other.firstname.lower()))

         def __lt__(self, other):
             return ((self.lastname.lower(), self.firstname.lower()) <
                     (other.lastname.lower(), other.firstname.lower()))

  使用 *total_ordering* 装饰器时，将会自动填充其余的比较方法。

  （由 Raymond Hettinger 贡献。）

* 为帮助移植 Python 2 程序，"functools.cmp_to_key()" 函数可将旧式的比
  较函数转换为新式的 *key function*:

  >>> # locale-aware sort order
  >>> sorted(iterable, key=cmp_to_key(locale.strcoll)) 

  有关排序示例和简短的排序教程，请参阅 排序的技术 教程。

  （由 Raymond Hettinger 贡献。）


itertools
---------

* "itertools" 模块有一个新的 "accumulate()" 函数，该函数模仿 APL 的
  *scan* 运算符和 Numpy 的 *accumulate* 函数：

  >>> from itertools import accumulate
  >>> list(accumulate([8, 2, 50]))
  [8, 10, 60]

  >>> prob_dist = [0.1, 0.4, 0.2, 0.3]
  >>> list(accumulate(prob_dist))      # cumulative probability distribution
  [0.1, 0.5, 0.7, 1.0]

  有关使用 "accumulate()" 的示例，请参阅 random 模块的示例。

  （由 Raymond Hettinger 贡献，并融合了 Mark Dickinson 的设计建议。）


collections
-----------

* "collections.Counter" 类现在支持两种形式的原地减法操作：现有的 *-=*
  运算符实现的是 饱和减法 (即结果不会低于零)，而新增的 "subtract()" 方
  法则实现常规减法 (允许结果为负值)。前者适用于 多重集 (仅包含正计数的
  场景)，后者更适合允许负计数的使用场景。

  >>> from collections import Counter
  >>> tally = Counter(dogs=5, cats=3)
  >>> tally -= Counter(dogs=2, cats=8)    # saturating subtraction
  >>> tally
  Counter({'dogs': 3})

  >>> tally = Counter(dogs=5, cats=3)
  >>> tally.subtract(dogs=2, cats=8)      # regular subtraction
  >>> tally
  Counter({'dogs': 3, 'cats': -5})

  （由 Raymond Hettinger 贡献。）

* "collections.OrderedDict" 类有一个新方法 "move_to_end()"，它接受一个
  现有的键并将其移动到有序序列的第一个或最后一个位置。

  默认情况下，将项目移动到最后一个位置。这相当于用 "od[k] = od.pop(k)"
  更新一个条目。

  快速移动到末尾的操作对于重新排序条目很有用。例如，有序字典可以用来跟
  踪访问顺序，通过将条目从最旧的更新到最近访问的。

  >>> from collections import OrderedDict
  >>> d = OrderedDict.fromkeys(['a', 'b', 'X', 'd', 'e'])
  >>> list(d)
  ['a', 'b', 'X', 'd', 'e']
  >>> d.move_to_end('X')
  >>> list(d)
  ['a', 'b', 'd', 'e', 'X']

  （由 Raymond Hettinger 贡献。）

* "collections.deque" 类新增了两个方法 "count()" 和 "reverse()"，使它
  们更易于替代 "list" 对象：

  >>> from collections import deque
  >>> d = deque('simsalabim')
  >>> d.count('s')
  2
  >>> d.reverse()
  >>> d
  deque(['m', 'i', 'b', 'a', 'l', 'a', 's', 'm', 'i', 's'])

  （由 Raymond Hettinger 贡献。）


threading
---------

"threading" 模块有一个新的 "Barrier" 同步类，用于使多个线程等待，直到
它们都达到一个共同的屏障点。屏障对于确保具有多个先决条件的任务在所有前
置任务完成之前不运行非常有用。

屏障可以与任意数量的线程一起工作。这是对仅适用于两个线程的 会合点 的泛
化。

作为两阶段循环屏障实现，"Barrier" 对象适用于循环中使用。独立的 *填充*
和 *排空* 阶段确保所有线程在任何一个线程循环回并重新进入屏障之前都被释
放（排空）。屏障在每个周期后完全重置。

使用屏障的示例：

   from threading import Barrier, Thread

   def get_votes(site):
       ballots = conduct_election(site)
       all_polls_closed.wait()        # do not count until all polls are closed
       totals = summarize(ballots)
       publish(site, totals)

   all_polls_closed = Barrier(len(sites))
   for site in sites:
       Thread(target=get_votes, args=(site,)).start()

在这个示例中，屏障强制执行一个规则，即在所有投票站关闭之前，任何投票站
都不能计票。请注意，使用屏障的解决方案与使用 "threading.Thread.join()"
的解决方案类似，但线程在越过屏障点后仍然保持活动状态并继续工作（汇总选
票）。

如果任何前置任务可能会挂起或延迟，可以创建一个带有可选 *timeout* 参数
的屏障。然后，如果在超时期限内所有前置任务都没有到达屏障点，所有等待的
线程将被释放，并引发 "BrokenBarrierError" 异常：

   def get_votes(site):
       ballots = conduct_election(site)
       try:
           all_polls_closed.wait(timeout=midnight - time.now())
       except BrokenBarrierError:
           lockbox = seal_ballots(ballots)
           queue.put(lockbox)
       else:
           totals = summarize(ballots)
           publish(site, totals)

在这个示例中，屏障执行了一个更健壮的规则。如果某些选举站在午夜前没有完
成，屏障将超时，选票将被封存并放入队列中以供后续处理。

请参阅 屏障同步模式 了解更多关于如何在并行计算中使用屏障的示例。此外，
在 信号量小册子 的 *第3.6节* 中也有一个简单但详尽的屏障解释。

（由 Kristján Valur Jónsson 贡献，并由 Jeffrey Yasskin 在 bpo-8777 中
进行 API 审查。）


datetime 和 time
----------------

* "datetime" 模块新增了一种类型 "timezone"，它通过返回固定的 UTC 偏移
  量和时区名称来实现 "tzinfo" 接口。这使得创建带有时区信息的 datetime
  对象变得更加容易:

     >>> from datetime import datetime, timezone

     >>> datetime.now(timezone.utc)
     datetime.datetime(2010, 12, 8, 21, 4, 2, 923754, tzinfo=datetime.timezone.utc)

     >>> datetime.strptime("01/01/2000 12:00 +0000", "%m/%d/%Y %H:%M %z")
     datetime.datetime(2000, 1, 1, 12, 0, tzinfo=datetime.timezone.utc)

* 此外，"timedelta" 对象现在可以与 "float" 相乘，并且可以被 "float" 和
  "int" 对象除。同时，"timedelta" 对象现在可以相互除。

* "datetime.date.strftime()" 方法不再限制于 1900 年之后的年份。新的支
  持年份范围是从 1000 年到 9999 年（含）。

* Whenever a two-digit year is used in a time tuple, the
  interpretation has been governed by "time.accept2dyear".  The
  default is "True" which means that for a two-digit year, the century
  is guessed according to the POSIX rules governing the "%y" strptime
  format.

  Starting with Py3.2, use of the century guessing heuristic will emit
  a "DeprecationWarning".  Instead, it is recommended that
  "time.accept2dyear" be set to "False" so that large date ranges can
  be used without guesswork:

     >>> import time, warnings
     >>> warnings.resetwarnings()      # remove the default warning filters

     >>> time.accept2dyear = True      # guess whether 11 means 11 or 2011
     >>> time.asctime((11, 1, 1, 12, 34, 56, 4, 1, 0))
     Warning (from warnings module):
       ...
     DeprecationWarning: Century info guessed for a 2-digit year.
     'Fri Jan  1 12:34:56 2011'

     >>> time.accept2dyear = False     # use the full range of allowable dates
     >>> time.asctime((11, 1, 1, 12, 34, 56, 4, 1, 0))
     'Fri Jan  1 12:34:56 11'

  Several functions now have significantly expanded date ranges.  When
  "time.accept2dyear" is false, the "time.asctime()" function will
  accept any year that fits in a C int, while the "time.mktime()" and
  "time.strftime()" functions will accept the full range supported by
  the corresponding operating system functions.

（由 Alexander Belopolsky 和 Victor Stinner 在 bpo-1289118, bpo-5094,
bpo-6641, bpo-2706, bpo-1777412, bpo-8013 和 bpo-10827 中贡献。）


math
----

"math" 模块基于 C99 标准增加了六个新函数。

"isfinite()" 函数提供了一种可靠且快速的方法来检测特殊值。它对常规数字
返回 "True"，对 *Nan* 或 *Infinity* 返回 "False"：

>>> from math import isfinite
>>> [isfinite(x) for x in (123, 4.56, float('Nan'), float('Inf'))]
[True, True, False, False]

"expm1()" 函数用于计算 "e**x - 1" (其中 *x* 为较小数值)，且不会产生因
相减两个近似相等数值而导致精度损失的问题。

>>> from math import expm1
>>> expm1(0.013671875)   # more accurate way to compute e**x-1 for a small x
0.013765762467652909

"erf()" 函数计算概率积分或 高斯误差函数。其互补误差函数 "erfc()" 的计
算公式为 "1 - erf(x)"：

   >>> from math import erf, erfc, sqrt
   >>> erf(1.0/sqrt(2.0))   # portion of normal distribution within 1 standard deviation
   0.682689492137086
   >>> erfc(1.0/sqrt(2.0))  # portion of normal distribution outside 1 standard deviation
   0.31731050786291404
   >>> erf(1.0/sqrt(2.0)) + erfc(1.0/sqrt(2.0))
   1.0

"gamma()" 函数是阶乘函数的连续扩展。详情请见
https://en.wikipedia.org/wiki/Gamma_function。由于该函数与阶乘相关，即
使对于小的 *x* 值，其值也会变得很大，因此还有一个 "lgamma()" 函数用于
计算伽马函数的自然对数：

>>> from math import gamma, lgamma
>>> gamma(7.0)           # six factorial
720.0
>>> lgamma(801.0)        # log(800 factorial)
4551.950730698041

（由 Mark Dickinson 贡献）


abc
---

"abc" 模块现在支持 "abstractclassmethod()" 和 "abstractstaticmethod()"
。

这些工具使得可以定义一个要求实现特定 "classmethod()" 或
"staticmethod()" 的 *抽象基类*：

   class Temperature(metaclass=abc.ABCMeta):
       @abc.abstractclassmethod
       def from_fahrenheit(cls, t):
           ...
       @abc.abstractclassmethod
       def from_celsius(cls, t):
           ...

（补丁由 Daniel Urban 在 bpo-5867 中提交。）


io
--

"io.BytesIO" 类新增了一个方法 "getbuffer()"，其功能类似于
"memoryview()"。该方法会创建一个数据的可编辑视图，且不会生成数据的副本
。该缓冲区支持随机访问和切片表示法，非常适合进行原地编辑操作:

   >>> REC_LEN, LOC_START, LOC_LEN = 34, 7, 11

   >>> def change_location(buffer, record_number, location):
   ...     start = record_number * REC_LEN + LOC_START
   ...     buffer[start: start+LOC_LEN] = location

   >>> import io

   >>> byte_stream = io.BytesIO(
   ...     b'G3805  storeroom  Main chassis    '
   ...     b'X7899  shipping   Reserve cog     '
   ...     b'L6988  receiving  Primary sprocket'
   ... )
   >>> buffer = byte_stream.getbuffer()
   >>> change_location(buffer, 1, b'warehouse  ')
   >>> change_location(buffer, 0, b'showroom   ')
   >>> print(byte_stream.getvalue())
   b'G3805  showroom   Main chassis    '
   b'X7899  warehouse  Reserve cog     '
   b'L6988  receiving  Primary sprocket'

（由 Antoine Pitrou 在 bpo-5506 中贡献。）


reprlib
-------

When writing a "__repr__()" method for a custom container, it is easy
to forget to handle the case where a member refers back to the
container itself. Python's builtin objects such as "list" and "set"
handle self-reference by displaying "..." in the recursive part of the
representation string.

To help write such "__repr__()" methods, the "reprlib" module has a
new decorator, "recursive_repr()", for detecting recursive calls to
"__repr__()" and substituting a placeholder string instead:

   >>> class MyList(list):
   ...     @recursive_repr()
   ...     def __repr__(self):
   ...         return '<' + '|'.join(map(repr, self)) + '>'
   ...
   >>> m = MyList('abc')
   >>> m.append(m)
   >>> m.append('x')
   >>> print(m)
   <'a'|'b'|'c'|...|'x'>

（由 Raymond Hettinger 在 bpo-9826 和  bpo-9840 中贡献。）


logging
-------

除了上述基于字典的配置外，"logging" 包还有许多其他改进。

日志模块的文档已新增一份 基础教程、一份 高级教程 以及一份包含日志实践
案例的 指南。这些文档是学习日志功能的最佳途径。

"logging.basicConfig()" 配置函数新增了一个 *style* 参数，用于支持三种
不同的字符串格式化方式。该参数默认值为 "%"，表示传统的 %-格式化；可设
置为 "{"，采用新的 "str.format()" 格式化风格；也可设置为 "$"，使用
"string.Template" 提供的类 shell 风格格式化。以下三种配置方式是等效的:

   >>> from logging import basicConfig
   >>> basicConfig(style='%', format="%(name)s -> %(levelname)s: %(message)s")
   >>> basicConfig(style='{', format="{name} -> {levelname} {message}")
   >>> basicConfig(style='$', format="$name -> $levelname: $message")

If no configuration is set-up before a logging event occurs, there is
now a default configuration using a "StreamHandler" directed to
"sys.stderr" for events of "WARNING" level or higher.  Formerly, an
event occurring before a configuration was set-up would either raise
an exception or silently drop the event depending on the value of
"logging.raiseExceptions".  The new default handler is stored in
"logging.lastResort".

过滤器的使用已经简化。现在不再需要创建 "Filter" 对象，谓词可以是任何返
回 "True" 或 "False" 的 Python 可调用对象。

还有许多其他改进，增加了灵活性并简化了配置。请参阅模块文档，了解
Python 3.2 中所有更改的完整列表。


csv
---

"csv" 模块现在支持一个新的方言，"unix_dialect"，它对所有字段应用引号，
并使用传统的 Unix 风格，以 "'\n'" 作为行终止符。注册的方言名称为
"unix"。

"csv.DictWriter" 有一个新的 "writeheader()" 方法，用于写入初始行以记录
字段名称:

   >>> import csv, sys
   >>> w = csv.DictWriter(sys.stdout, ['name', 'dept'], dialect='unix')
   >>> w.writeheader()
   "name","dept"
   >>> w.writerows([
   ...     {'name': 'tom', 'dept': 'accounting'},
   ...     {'name': 'susan', 'dept': 'Salesl'}])
   "tom","accounting"
   "susan","sales"

（新方言由 Jay Talbot 在 bpo-5975 中建议，新方法由 Ed Abraham 在
bpo-1537721 中建议。）


contextlib
----------

有一个新的且略显震撼的工具 "ContextDecorator"，它有助于创建一个既可以
作为函数装饰器又可以作为 *上下文管理器* 的双重用途的上下文管理器。

为了方便起见，这一新功能被 "contextmanager()" 使用，因此无需额外努力即
可支持这两种角色。

基本思想是，上下文管理器和函数装饰器都可以用于前置动作和后置动作的包装
器。上下文管理器使用 "with" 语句包装一组语句，而函数装饰器包装一个函数
内的一组语句。因此，有时需要编写一个可以在任一角色中使用的前置动作或后
置动作包装器。

例如，有时需要用一个日志记录器包装函数或一组语句，以跟踪进入和退出时间
。与其为该任务编写一个函数装饰器和一个上下文管理器，不如使用
"contextmanager()" 在单一定义中提供这两种能力:

   from contextlib import contextmanager
   import logging

   logging.basicConfig(level=logging.INFO)

   @contextmanager
   def track_entry_and_exit(name):
       logging.info('Entering: %s', name)
       yield
       logging.info('Exiting: %s', name)

以前，这只能用作上下文管理器:

   with track_entry_and_exit('widget loader'):
       print('Some time consuming activity goes here')
       load_widget()

现在，它也可以用作装饰器:

   @track_entry_and_exit('widget loader')
   def activity():
       print('Some time consuming activity goes here')
       load_widget()

试图同时满足两种角色对技术有一些限制。上下文管理器通常具有返回一个可被
"with" 语句使用的参数的灵活性，但函数装饰器没有类似的特性。

在上面的示例中，*track_entry_and_exit* 上下文管理器没有一种简洁的方式
来返回一个日志实例，以供封闭语句体中使用。

（由 Michael Foord 在 bpo-9110 中贡献。）


decimal 和 fractions
--------------------

Mark Dickinson 设计了一个优雅且高效的方案，确保不同数值数据类型在实际
值相等时具有相同的哈希值（bpo-8188）:

   assert hash(Fraction(3, 2)) == hash(1.5) == \
          hash(Decimal("1.5")) == hash(complex(1.5, 0))

Some of the hashing details are exposed through a new attribute,
"sys.hash_info", which describes the bit width of the hash value, the
prime modulus, the hash values for *infinity* and *nan*, and the
multiplier used for the imaginary part of a number:

>>> sys.hash_info 
sys.hash_info(width=64, modulus=2305843009213693951, inf=314159, nan=0, imag=1000003)

An early decision to limit the inter-operability of various numeric
types has been relaxed.  It is still unsupported (and ill-advised) to
have implicit mixing in arithmetic expressions such as "Decimal('1.1')
+ float('1.1')" because the latter loses information in the process of
constructing the binary float.  However, since existing floating point
value can be converted losslessly to either a decimal or rational
representation, it makes sense to add them to the constructor and to
support mixed-type comparisons.

* "decimal.Decimal" 构造函数现在直接接受 "float" 对象，因此不再需要使
  用 "from_float()" 方法（bpo-8257）。

* 现在完全支持混合类型比较，以便 "Decimal" 对象可以直接与 "float" 和
  "fractions.Fraction" 进行比较（bpo-2531 和 bpo-8188）。

Similar changes were made to "fractions.Fraction" so that the
"from_float()" and "from_decimal()" methods are no longer needed
(bpo-8294):

>>> from decimal import Decimal
>>> from fractions import Fraction
>>> Decimal(1.1)
Decimal('1.100000000000000088817841970012523233890533447265625')
>>> Fraction(1.1)
Fraction(2476979795053773, 2251799813685248)

Another useful change for the "decimal" module is that the
"Context.clamp" attribute is now public.  This is useful in creating
contexts that correspond to the decimal interchange formats specified
in IEEE 754 (see bpo-8540).

（由 Mark Dickinson 和 Raymond Hettinger贡献。）


ftp
---

"ftplib.FTP" 类现在支持上下文管理协议，可以无条件地捕获 "socket.error"
异常，并在完成操作时关闭 FTP 连接：

   >>> from ftplib import FTP
   >>> with FTP("ftp1.at.proftpd.org") as ftp:
           ftp.login()
           ftp.dir()

   '230 Anonymous login ok, restrictions apply.'
   dr-xr-xr-x   9 ftp      ftp           154 May  6 10:43 .
   dr-xr-xr-x   9 ftp      ftp           154 May  6 10:43 ..
   dr-xr-xr-x   5 ftp      ftp          4096 May  6 10:43 CentOS
   dr-xr-xr-x   3 ftp      ftp            18 Jul 10  2008 Fedora

其他文件型对象如 "mmap.mmap" 和 "fileinput.input()" 也有了支持自动关闭
的上下文管理器:

   with fileinput.input(files=('log1.txt', 'log2.txt')) as f:
       for line in f:
           process(line)

（由 Tarek Ziadé 和 Giampaolo Rodolà 在 bpo-4972 贡献，由 Georg Brandl
在 bpo-8046 和 bpo-1286 贡献。）

"FTP_TLS" 类现在接受一个 *context* 参数，这是一个 "ssl.SSLContext" 对
象，允许将 SSL 配置选项、证书和私钥捆绑到一个单一的（可能是长寿命的）
结构体中。

（由 Giampaolo Rodolà 在 bpo-8806 中贡献。）


popen
-----

"os.popen()" 和 "subprocess.Popen()" 函数现在支持使用 "with" 语句来自
动关闭文件描述符。

（由 Antoine Pitrou 和 Brian Curtin 在 bpo-7461 和 bpo-10554 中贡献。
）


select
------

The "select" module now exposes a new, constant attribute, "PIPE_BUF",
which gives the minimum number of bytes which are guaranteed not to
block when "select.select()" says a pipe is ready for writing.

>>> import select
>>> select.PIPE_BUF  
512

（在 Unix 系统上可用。 由 Sébastien Sablé 在 bpo-9862 中提供补丁）


gzip 和 zipfile
---------------

"gzip.GzipFile" 现在实现了 "io.BufferedIOBase" *抽象基类* (除了
"truncate()")。它还有一个 "peek()" 方法，并支持不可 seek 的以及零填充
的文件对象。

"gzip" 模块还增加了 "compress()" 和 "decompress()" 函数，以便更容易地
进行内存中的压缩和解压缩。请记住，文本在压缩和解压缩之前需要编码为
"bytes"：

>>> import gzip
>>> s = 'Three shall be the number thou shalt count, '
>>> s += 'and the number of the counting shall be three'
>>> b = s.encode()                        # convert to utf-8
>>> len(b)
89
>>> c = gzip.compress(b)
>>> len(c)
77
>>> gzip.decompress(c).decode()[:42]      # decompress and convert to text
'Three shall be the number thou shalt count'

（由 Anand B. Pillai 在 bpo-3488 中贡献，由Antoine Pitrou, Nir Aides
和 Brian Curtin 在 bpo-9962，bpo-1675951 ，bpo-7471 和 bpo-2846 中贡献
。）

Also, the "zipfile.ZipExtFile" class was reworked internally to
represent files stored inside an archive.  The new implementation is
significantly faster and can be wrapped in an "io.BufferedReader"
object for more speedups.  It also solves an issue where interleaved
calls to *read* and *readline* gave the wrong results.

（补丁由 Nir Aides 在 bpo-7610 中提交。）


tarfile
-------

"TarFile" 类现在可以用作上下文管理器。此外，其 "add()" 方法有一个新的
选项 *filter*，它控制哪些文件被添加到存档中，并允许编辑文件元数据。

新的 *filter* 选项取代了旧的、灵活性较差的 *exclude* 参数，后者现已弃
用。如果指定，可选的 *filter* 参数需要是一个 *关键字参数*。用户提供的
过滤函数接受一个 "TarInfo" 对象，并返回一个更新的 "TarInfo" 对象，如果
希望排除该文件，函数可以返回 "None":

   >>> import tarfile, glob

   >>> def myfilter(tarinfo):
   ...     if tarinfo.isfile():             # only save real files
   ...         tarinfo.uname = 'monty'      # redact the user name
   ...         return tarinfo

   >>> with tarfile.open(name='myarchive.tar.gz', mode='w:gz') as tf:
   ...     for filename in glob.glob('*.txt'):
   ...         tf.add(filename, filter=myfilter)
   ...     tf.list()
   -rw-r--r-- monty/501        902 2011-01-26 17:59:11 annotations.txt
   -rw-r--r-- monty/501        123 2011-01-26 17:59:11 general_questions.txt
   -rw-r--r-- monty/501       3514 2011-01-26 17:59:11 prion.txt
   -rw-r--r-- monty/501        124 2011-01-26 17:59:11 py_todo.txt
   -rw-r--r-- monty/501       1399 2011-01-26 17:59:11 semaphore_notes.txt

（由 Tarek Ziadé 提议并由 Lars Gustäbel 在 bpo-6856 中实现。）


hashlib
-------

"hashlib" 模块有两个新的常量属性，列出了在所有实现中保证存在的哈希算法
和当前实现中可用的算法:

   >>> import hashlib

   >>> hashlib.algorithms_guaranteed
   {'sha1', 'sha224', 'sha384', 'sha256', 'sha512', 'md5'}

   >>> hashlib.algorithms_available
   {'md2', 'SHA256', 'SHA512', 'dsaWithSHA', 'mdc2', 'SHA224', 'MD4', 'sha256',
   'sha512', 'ripemd160', 'SHA1', 'MDC2', 'SHA', 'SHA384', 'MD2',
   'ecdsa-with-SHA1','md4', 'md5', 'sha1', 'DSA-SHA', 'sha224',
   'dsaEncryption', 'DSA', 'RIPEMD160', 'sha', 'MD5', 'sha384'}

（由 Carl Chenet 在 bpo-7418 中建议。）


ast
---

"ast" 模块提供了一个用于安全评估表达式字符串的通用工具，使用 Python 字
面量语法。"ast.literal_eval()" 函数作为内置 "eval()" 函数的安全替代，
后者容易被滥用。Python 3.2 将 "bytes" 和 "set" 字面量添加到支持的类型
列表中：字符串、字节、数字、元组、列表、字典、集合、布尔值和 "None"。

   >>> from ast import literal_eval

   >>> request = "{'req': 3, 'func': 'pow', 'args': (2, 0.5)}"
   >>> literal_eval(request)
   {'args': (2, 0.5), 'req': 3, 'func': 'pow'}

   >>> request = "os.system('do something harmful')"
   >>> literal_eval(request)
   Traceback (most recent call last):
     ...
   ValueError: malformed node or string: <_ast.Call object at 0x101739a10>

（由Benjamin Peterson 和 Georg Brandl 实现。）


os
--

不同的操作系统对文件名和环境变量使用各种编码。"os" 模块提供了两个新函
数，"fsencode()" 和 "fsdecode()"，用于编码和解码文件名：

>>> import os
>>> filename = 'Sehenswürdigkeiten'
>>> os.fsencode(filename)
b'Sehensw\xc3\xbcrdigkeiten'

Some operating systems allow direct access to encoded bytes in the
environment.  If so, the "os.supports_bytes_environ" constant will be
true.

为了直接访问编码的环境变量（如果可用），使用新的 "os.getenvb()" 函数，
或者使用 "os.environb"，它是 "os.environ" 的字节版本。

（由 Victor Stinner 贡献。）


shutil
------

"shutil.copytree()" 函数增加了两个新选项:

* *ignore_dangling_symlinks*：当 "symlinks=False" 时，函数会复制由符号
  链接指向的文件，而不是符号链接本身。此选项将静默处理文件不存在时引发
  的错误。

* *copy_function*：是一个用于复制文件的可调用对象。默认使用
  "shutil.copy2()"。

（由 Tarek Ziadé 贡献。）

此外，"shutil" 模块现在支持对 zip 文件、未压缩的 tar 文件、gzip 压缩的
tar 文件和 bzip 压缩的 tar 文件的 归档操作。还有用于注册其他归档文件格
式（如 xz 压缩的 tar 文件或自定义格式）的函数。

主要函数是 "make_archive()" 和 "unpack_archive()"。默认情况下，两者操
作当前目录（可以通过 "os.chdir()" 设置）及其任何子目录。归档文件名需要
指定完整路径名。归档步骤是非破坏性的（原始文件保持不变）。

   >>> import shutil, pprint

   >>> os.chdir('mydata')  # change to the source directory
   >>> f = shutil.make_archive('/var/backup/mydata',
   ...                         'zip')      # archive the current directory
   >>> f                                   # show the name of archive
   '/var/backup/mydata.zip'
   >>> os.chdir('tmp')                     # change to an unpacking
   >>> shutil.unpack_archive('/var/backup/mydata.zip')  # recover the data

   >>> pprint.pprint(shutil.get_archive_formats())  # display known formats
   [('bztar', "bzip2'ed tar-file"),
    ('gztar', "gzip'ed tar-file"),
    ('tar', 'uncompressed tar file'),
    ('zip', 'ZIP file')]

   >>> shutil.register_archive_format(     # register a new archive format
   ...     name='xz',
   ...     function=xz.compress,           # callable archiving function
   ...     extra_args=[('level', 8)],      # arguments to the function
   ...     description='xz compression'
   ... )

（由 Tarek Ziadé 贡献。）


sqlite3
-------

"sqlite3" 模块被更新至 pysqlite 2.6.0 版。 它拥有两个新功能。

* The "sqlite3.Connection.in_transit" attribute is true if there is an
  active transaction for uncommitted changes.

* "sqlite3.Connection.enable_load_extension()" 和
  "sqlite3.Connection.load_extension()" 方法允许你从 ".so" 文件加载
  SQLite 扩展。一个著名的扩展是随 SQLite 分发的全文搜索扩展。

（由 R. David Murray 和 Shashwat Anand 在 bpo-8845 中贡献。）


html
----

引入了一个新的 "html" 模块，其中只有一个函数 "escape()"，用于转义 HTML
标记中的保留字符：

>>> import html
>>> html.escape('x > 2 && x < 7')
'x &gt; 2 &amp;&amp; x &lt; 7'


socket
------

"socket" 模块有两项新改进。

* Socket objects now have a "detach()" method which puts the socket
  into closed state without actually closing the underlying file
  descriptor.  The latter can then be reused for other purposes.
  (Added by Antoine Pitrou; bpo-8524.)

* "socket.create_connection()" 现在支持上下文管理协议，以无条件消耗
  "socket.error" 异常，并在完成后关闭套接字。（由 Giampaolo Rodolà 在
  bpo-9794 中贡献。）


ssl
---

"ssl" 模块添加了许多功能以满足安全（加密、认证）互联网连接的常见需求：

* 一个新的类，"SSLContext"，用作持久SSL数据的容器，例如协议设置、证书
  、私钥和各种其他选项。它包括一个 "wrap_socket()" 方法，用于从SSL上下
  文创建SSL套接字。

* A new function, "ssl.match_hostname()", supports server identity
  verification for higher-level protocols by implementing the rules of
  HTTPS (from **RFC 2818**) which are also suitable for other
  protocols.

* The "ssl.wrap_socket()" constructor function now takes a *ciphers*
  argument.  The *ciphers* string lists the allowed encryption
  algorithms using the format described in the OpenSSL documentation.

* 当与较新版本的 OpenSSL 库链接时，"ssl" 模块现在支持 TLS 协议的服务器
  名称指示（Server Name Indication，SNI）扩展。该特性允许在单个 IP 端
  口上为多个使用不同证书的“虚拟主机”提供服务。需要注意的是，此扩展仅在
  客户端模式下受支持，并且需要通过向 "ssl.SSLContext.wrap_socket()" 方
  法传递 *server_hostname* 参数来激活。

* 已向 "ssl" 模块添加了各种选项，例如 "OP_NO_SSLv2"，该选项禁用了不安
  全且已过时的SSLv2协议。

* 扩展现在加载了所有OpenSSL密码和摘要算法。如果某些SSL证书无法验证，它
  们将被报告为“未知算法”错误。

* The version of OpenSSL being used is now accessible using the module
  attributes "ssl.OPENSSL_VERSION" (a string),
  "ssl.OPENSSL_VERSION_INFO" (a 5-tuple), and
  "ssl.OPENSSL_VERSION_NUMBER" (an integer).

（由 Antoine Pitrou 在 bpo-8850,  bpo-1589, bpo-8322, bpo-5639,
bpo-4870, bpo-8484 和 bpo-8321 中贡献。）


nntp
----

The "nntplib" module has a revamped implementation with better bytes
and text semantics as well as more practical APIs.  These improvements
break compatibility with the nntplib version in Python 3.1, which was
partly dysfunctional in itself.

Support for secure connections through both implicit (using
"nntplib.NNTP_SSL") and explicit (using "nntplib.NNTP.starttls()") TLS
has also been added.

（由 Antoine Pitrou 在 bpo-9360 中贡献，由 Andrew Vant 在 bpo-1926 中
贡献。）


certificates
------------

"http.client.HTTPSConnection"、"urllib.request.HTTPSHandler" 和
"urllib.request.urlopen()" 现在接受可选参数，以允许对服务器证书进行检
查，以验证一组证书颁发机构，这是公共HTTPS使用的推荐做法。

（由 Antoine Pitrou 添加，bpo-9003。）


imaplib
-------

通过新的 "imaplib.IMAP4.starttls" 方法，标准IMAP4连接上增加了显式TLS支
持。

（由 Lorenzo M. Catucci 和 Antoine Pitrou 在 bpo-4471 中贡献。）


http.client
-----------

"http.client" 模块中进行了一些小的API改进。不再支持旧式HTTP 0.9简单响
应，所有类中的 *strict* 参数已被弃用。

"HTTPConnection" 和 "HTTPSConnection" 类现在有一个 *source_address* 参
数，用于指示（主机，端口）元组，表明HTTP连接是从哪里建立的。

为 "HTTPSConnection" 增加了证书检查和HTTPS虚拟主机的支持。

连接对象上的 "request()" 方法允许一个可选的 *body* 参数，以便可以使用
*文件对象* 来提供请求的内容。方便的是，*body* 参数现在也接受一个 *可迭
代* 对象，只要它包含一个明确的 "Content-Length" 头部。这个扩展接口比以
前更加灵活。

为了通过代理服务器建立 HTTPS 连接，新增了一个 "set_tunnel()" 方法，用
于设置 HTTP Connect 隧道的主机和端口。

为了与 "http.server" 的行为保持一致，HTTP 客户端库现在也使用
ISO-8859-1（Latin-1）编码对头部进行编码。它已经对传入的头部这样做了，
所以现在传入和传出流量的行为是一致的。（参见 Armin Ronacher 在
bpo-10980 中的工作。）


unittest
--------

unittest 模块有许多改进，支持包的测试发现、在交互式提示符下更容易进行
实验、新的测试用例方法、改进的测试失败诊断消息以及更好的方法名称。

* 命令行调用 "python -m unittest" 现在接受文件路径而不是模块名来运行特
  定的测试 (bpo-10620)。新的测试发现可以在包内找到测试，定位从顶级目录
  可导入的任何测试。顶级目录可以用 "-t" 选项指定，用 "-p" 匹配文件的模
  式，以及用 "-s" 指定开始发现的目录：

     $ python -m unittest discover -s my_proj_dir -p _test.py

  （由 Michael Foord 贡献）

* Experimentation at the interactive prompt is now easier because the
  "unittest.case.TestCase" class can now be instantiated without
  arguments:

  >>> from unittest import TestCase
  >>> TestCase().assertEqual(pow(2, 3), 8)

  （由 Michael Foord 贡献）

* "unittest" 模块有两个新方法，"assertWarns()" 和 "assertWarnsRegex()"
  ，用于验证给定警告类型是否由被测试代码触发：

     with self.assertWarns(DeprecationWarning):
         legacy_function('XYZ')

  （由 Antoine Pitrou 在 bpo-9754 中贡献。）

  另一个新方法，"assertCountEqual()" 用于比较两个可迭代对象，以确定它
  们的元素计数是否相等（无论顺序如何，相同元素的出现次数是否相同）:

     def test_anagram(self):
         self.assertCountEqual('algorithm', 'logarithm')

  （由 Raymond Hettinger 贡献。）

* unittest 模块的主要特性之一是当测试失败时，努力生成有意义的诊断信息
  。在可能的情况下，失败记录会附带输出内容的差异。这对于分析失败的测试
  运行的日志文件特别有帮助。然而，由于差异有时可能非常庞大，因此有一个
  新的 "maxDiff" 属性用于设置显示的差异最大长度。

* 此外，模块中的方法名称已经进行了多项清理。

  For example, "assertRegex()" is the new name for
  "assertRegexpMatches()" which was misnamed because the test uses
  "re.search()", not "re.match()".  Other methods using regular
  expressions are now named using short form "Regex" in preference to
  "Regexp" -- this matches the names used in other unittest
  implementations, matches Python's old name for the "re" module, and
  it has unambiguous camel-casing.

  （由 Raymond Hettinger 贡献并由 Ezio Melotti 实现。）

* 为了提高一致性，一些长期存在的方法别名正在被弃用，转而使用首选名称：

     +---------------------------------+--------------------------------+
     | 旧名称                          | 首选名称                       |
     |=================================|================================|
     | "assert_()"                     | "assertTrue()"                 |
     +---------------------------------+--------------------------------+
     | "assertEquals()"                | "assertEqual()"                |
     +---------------------------------+--------------------------------+
     | "assertNotEquals()"             | "assertNotEqual()"             |
     +---------------------------------+--------------------------------+
     | "assertAlmostEquals()"          | "assertAlmostEqual()"          |
     +---------------------------------+--------------------------------+
     | "assertNotAlmostEquals()"       | "assertNotAlmostEqual()"       |
     +---------------------------------+--------------------------------+

  Likewise, the "TestCase.fail*" methods deprecated in Python 3.1 are
  expected to be removed in Python 3.3.  Also see the 一些已被弃用的别
  名 section in the "unittest" documentation.

  （由 Ezio Melotti 在 bpo-9424 中贡献。）

* The "assertDictContainsSubset()" method was deprecated because it
  was misimplemented with the arguments in the wrong order.  This
  created hard-to-debug optical illusions where tests like
  "TestCase().assertDictContainsSubset({'a':1, 'b':2}, {'a':1})" would
  fail.

  （由 Raymond Hettinger 贡献。）


random
------

"random" 模块中的整数方法现在能更好地生成均匀分布。之前，它们使用
"int(n*random())" 计算选择，这在 *n* 不是二的幂时存在轻微偏差。现在，
从下一个二的幂的范围中进行多次选择，并且只有当选择落在 "0 <= x < n" 范
围内时才保留。受影响的函数和方法包括 "randrange()"、 "randint()"、
"choice()"、 "shuffle()" 和 "sample()"。

（由 Raymond Hettinger 在 bpo-9025 中贡献。）


poplib
------

"POP3_SSL" 类现在接受一个 *context* 参数，这是一个 "ssl.SSLContext" 对
象，允许将 SSL 配置选项、证书和私钥捆绑到一个单一的（可能是长期存在的
）结构体中。

（由 Giampaolo Rodolà 在 bpo-8807 中贡献。）


asyncore
--------

"asyncore.dispatcher" now provides a "handle_accepted()" method
returning a "(sock, addr)" pair which is called when a connection has
actually been established with a new remote endpoint. This is supposed
to be used as a replacement for old "handle_accept()" and avoids the
user  to call "accept()" directly.

（由 Giampaolo Rodolà 在 bpo-6706 中贡献。）


tempfile
--------

"tempfile" 模块有一个新的上下文管理器，"TemporaryDirectory"，它提供了
临时目录的简单确定性清理：

   with tempfile.TemporaryDirectory() as tmpdirname:
       print('created temporary dir:', tmpdirname)

（由 Neil Schemenauer 和 Nick Coghlan 在 bpo-5178 中贡献。）


inspect
-------

* "inspect" 模块有一个新函数 "getgeneratorstate()" 用来方便地标识一个
  生成器迭代器的当前状态:

     >>> from inspect import getgeneratorstate
     >>> def gen():
     ...     yield 'demo'
     >>> g = gen()
     >>> getgeneratorstate(g)
     'GEN_CREATED'
     >>> next(g)
     'demo'
     >>> getgeneratorstate(g)
     'GEN_SUSPENDED'
     >>> next(g, None)
     >>> getgeneratorstate(g)
     'GEN_CLOSED'

  （由 Rodolpho Eckhardt 和 Nick Coghlan 在 bpo-10220 中贡献。）

* 为了支持查找而不激活动态属性，"inspect" 模块有一个新函数，
  "getattr_static()"。与 "hasattr()" 不同，这是一个真正的只读搜索，保
  证在搜索过程中不会改变状态：

     >>> class A:
     ...     @property
     ...     def f(self):
     ...         print('Running')
     ...         return 10
     ...
     >>> a = A()
     >>> getattr(a, 'f')
     Running
     10
     >>> inspect.getattr_static(a, 'f')
     <property object at 0x1022bd788>

   （由 Michael Foord 贡献）


pydoc
-----

"pydoc" 模块现在提供了一个大幅改进的Web服务器接口，以及一个新的命令行
选项 "-b"，用于自动打开浏览器窗口以显示该服务器：

   $ pydoc3.2 -b

（由 Ron Adam 在 bpo-2001 中贡献。）


dis
---

"dis" 模块新增了两个用于检查代码的函数，"code_info()" 和 "show_code()"
。两者都为提供的函数、方法、源代码字符串或代码对象提供详细的代码对象信
息。前者返回一个字符串，后者将其打印出来：

   >>> import dis, random
   >>> dis.show_code(random.choice)
   Name:              choice
   Filename:          /Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/random.py
   Argument count:    2
   Kw-only arguments: 0
   Number of locals:  3
   Stack size:        11
   Flags:             OPTIMIZED, NEWLOCALS, NOFREE
   Constants:
      0: 'Choose a random element from a non-empty sequence.'
      1: 'Cannot choose from an empty sequence'
   Names:
      0: _randbelow
      1: len
      2: ValueError
      3: IndexError
   Variable names:
      0: self
      1: seq
      2: i

此外，"dis()" 函数现在接受字符串参数，以便常用的 "dis(compile(s, '',
'eval'))" 可以简化为 "dis(s)"：

   >>> dis('3*x+1 if x%2==1 else x//2')
     1           0 LOAD_NAME                0 (x)
                 3 LOAD_CONST               0 (2)
                 6 BINARY_MODULO
                 7 LOAD_CONST               1 (1)
                10 COMPARE_OP               2 (==)
                13 POP_JUMP_IF_FALSE       28
                16 LOAD_CONST               2 (3)
                19 LOAD_NAME                0 (x)
                22 BINARY_MULTIPLY
                23 LOAD_CONST               1 (1)
                26 BINARY_ADD
                27 RETURN_VALUE
           >>   28 LOAD_NAME                0 (x)
                31 LOAD_CONST               0 (2)
                34 BINARY_FLOOR_DIVIDE
                35 RETURN_VALUE

综合来看，这些改进使得探索CPython的实现方式以及亲自查看语言语法在底层
的作用变得更加容易。

（由 Nick Coghlan 在 bpo-9147 中贡献。）


dbm
---

所有数据库模块现在都支持 "get()" 和 "setdefault()" 方法。

（由 Ray Allen 在 bpo-9523 中建议。）


ctypes
------

一个新类型 "ctypes.c_ssize_t" 用来表示 C "ssize_t" 数据类型。


site
----

"site" 模块新增了三个用于报告给定 Python 安装版详细信息的函数。

* "getsitepackages()" 列出所有全局 site-packages 目录。

* "getuserbase()" 报告可用来存储数据的用户基准目录。

* "getusersitepackages()" 将揭示用户专属的 site-packages 目录路径。

   >>> import site
   >>> site.getsitepackages()
   ['/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/site-packages',
    '/Library/Frameworks/Python.framework/Versions/3.2/lib/site-python',
    '/Library/Python/3.2/site-packages']
   >>> site.getuserbase()
   '/Users/raymondhettinger/Library/Python/3.2'
   >>> site.getusersitepackages()
   '/Users/raymondhettinger/Library/Python/3.2/lib/python/site-packages'

部分 site 功能可方便地直接通过命令行访问：

   $ python -m site --user-base
   /Users/raymondhettinger/.local
   $ python -m site --user-site
   /Users/raymondhettinger/.local/lib/python3.2/site-packages

（由 Tarek Ziadé 在 bpo-6693 中贡献。）


sysconfig
---------

新增的 "sysconfig" 模块使得发现依赖于不同系统平台和安装版的安装路径和
配置变量更为简单直观。

该模块提供了对平台和版本信息获取函数的访问：

* "get_platform()" 将返回 *linux-i586* 或 *macosx-10.6-ppc* 形式的值。

* "get_python_version()" 将返回 Python 版本字符串如 "3.2"。

It also provides access to the paths and variables corresponding to
one of seven named schemes used by "distutils".  Those include
*posix_prefix*, *posix_home*, *posix_user*, *nt*, *nt_user*, *os2*,
*os2_home*:

* "get_paths()" 返回一个包含当前安装方案安装路径的字典。

* "get_config_vars()" 返回一个包含平台特定变量的字典。

还有一个方便的命令行界面：

   C:\Python32>python -m sysconfig
   Platform: "win32"
   Python version: "3.2"
   Current installation scheme: "nt"

   Paths:
           data = "C:\Python32"
           include = "C:\Python32\Include"
           platinclude = "C:\Python32\Include"
           platlib = "C:\Python32\Lib\site-packages"
           platstdlib = "C:\Python32\Lib"
           purelib = "C:\Python32\Lib\site-packages"
           scripts = "C:\Python32\Scripts"
           stdlib = "C:\Python32\Lib"

   Variables:
           BINDIR = "C:\Python32"
           BINLIBDEST = "C:\Python32\Lib"
           EXE = ".exe"
           INCLUDEPY = "C:\Python32\Include"
           LIBDEST = "C:\Python32\Lib"
           SO = ".pyd"
           VERSION = "32"
           abiflags = ""
           base = "C:\Python32"
           exec_prefix = "C:\Python32"
           platbase = "C:\Python32"
           prefix = "C:\Python32"
           projectbase = "C:\Python32"
           py_version = "3.2"
           py_version_nodot = "32"
           py_version_short = "3.2"
           srcdir = "C:\Python32"
           userbase = "C:\Documents and Settings\Raymond\Application Data\Python"

（由TarekZiadé 移出Distutils。）


pdb
---

"pdb" 调试器模块获得了一些可用性改进：

* "pdb.py" 现在有一个 "-c" 选项，用于执行 ".pdbrc" 脚本文件中给出的命
  令。

* 一个 ".pdbrc" 脚本文件可以包含 "continue" 和 "next" 命令，用于继续调
  试。

* The "Pdb" class constructor now accepts a *nosigint* argument.

* 新命令："l(list)"、"ll(long list)" 和 "source" 用于列出源代码。

* 新命令："display" 和 "undisplay" 用于显示或隐藏表达式值的变化。

* 新命令："interact" 用于启动一个包含当前作用域中全局和局部名称的交互
  式解释器。

* 可以通过断点编号清除断点。

（由Georg Brandl, Antonio Cuni 和 Ilya Sandler 贡献。）


configparser
------------

The "configparser" module was modified to improve usability and
predictability of the default parser and its supported INI syntax.
The old "ConfigParser" class was removed in favor of
"SafeConfigParser" which has in turn been renamed to "ConfigParser".
Support for inline comments is now turned off by default and section
or option duplicates are not allowed in a single configuration source.

配置解析器获得了一个基于映射协议的新 API：

   >>> parser = ConfigParser()
   >>> parser.read_string("""
   ... [DEFAULT]
   ... location = upper left
   ... visible = yes
   ... editable = no
   ... color = blue
   ...
   ... [main]
   ... title = Main Menu
   ... color = green
   ...
   ... [options]
   ... title = Options
   ... """)
   >>> parser['main']['color']
   'green'
   >>> parser['main']['editable']
   'no'
   >>> section = parser['options']
   >>> section['title']
   'Options'
   >>> section['title'] = 'Options (editable: %(editable)s)'
   >>> section['title']
   'Options (editable: no)'

新 API 是在经典 API 之上实现的，因此自定义解析器子类应能够无修改地使用
它。

配置解析器接受的 INI 文件结构体现在可以自定义。用户可以指定替代的选项/
值分隔符和注释前缀，更改 *DEFAULT* 部分的名称或切换插值语法。

支持可插拔插值，包括一个额外的插值处理程序 "ExtendedInterpolation"：

   >>> parser = ConfigParser(interpolation=ExtendedInterpolation())
   >>> parser.read_dict({'buildout': {'directory': '/home/ambv/zope9'},
   ...                   'custom': {'prefix': '/usr/local'}})
   >>> parser.read_string("""
   ... [buildout]
   ... parts =
   ...   zope9
   ...   instance
   ... find-links =
   ...   ${buildout:directory}/downloads/dist
   ...
   ... [zope9]
   ... recipe = plone.recipe.zope9install
   ... location = /opt/zope
   ...
   ... [instance]
   ... recipe = plone.recipe.zope9instance
   ... zope9-location = ${zope9:location}
   ... zope-conf = ${custom:prefix}/etc/zope.conf
   ... """)
   >>> parser['buildout']['find-links']
   '\n/home/ambv/zope9/downloads/dist'
   >>> parser['instance']['zope-conf']
   '/usr/local/etc/zope.conf'
   >>> instance = parser['instance']
   >>> instance['zope-conf']
   '/usr/local/etc/zope.conf'
   >>> instance['zope9-location']
   '/opt/zope'

此外还引入了一些较小的功能特性，例如：支持在读取操作中指定编码格式、为
获取函数（get-functions）指定回退值，以及直接从字典和字符串中读取数据
。

（所有改变均由 Łukasz Langa 贡献。）


urllib.parse
------------

对 "urllib.parse" 模块进行了一些可用性改进。

"urlparse()" 函数现在支持 IPv6 地址，如 **RFC 2732** 中所述：

>>> import urllib.parse
>>> urllib.parse.urlparse('http://[dead:beef:cafe:5417:affe:8FA3:deaf:feed]/foo/') 
ParseResult(scheme='http',
            netloc='[dead:beef:cafe:5417:affe:8FA3:deaf:feed]',
            path='/foo/',
            params='',
            query='',
            fragment='')

"urldefrag()" 函数现在返回一个 *具名元组*:

   >>> r = urllib.parse.urldefrag('http://python.org/about/#target')
   >>> r
   DefragResult(url='http://python.org/about/', fragment='target')
   >>> r[0]
   'http://python.org/about/'
   >>> r.fragment
   'target'

此外，"urlencode()" 函数现在更加灵活，可以接受字符串或字节类型作为
*query* 参数。如果是字符串，那么 *safe*、*encoding* 和 *error* 参数将
被传递给 "quote_plus()" 进行编码:

   >>> urllib.parse.urlencode([
   ...      ('type', 'telenovela'),
   ...      ('name', '¿Dónde Está Elisa?')],
   ...      encoding='latin-1')
   'type=telenovela&name=%BFD%F3nde+Est%E1+Elisa%3F'

如 解析ASCII编码字节 中所述，所有 "urllib.parse" 函数现在都接受 ASCII
编码的字节字符串作为输入，只要它们不与普通字符串混合。如果给定 ASCII
编码的字节字符串作为参数，返回类型也将是 ASCII 编码的字节字符串:

>>> urllib.parse.urlparse(b'http://www.python.org:80/about/') 
ParseResultBytes(scheme=b'http', netloc=b'www.python.org:80',
                 path=b'/about/', params=b'', query=b'', fragment=b'')

（由 Nick Coghlan、Dan Mahn 和 Senthil Kumaran 在 bpo-2987、bpo-5468
和 bpo-9873 中提供。）


mailbox
-------

由于 R. David Murray 的共同努力，"mailbox" 模块已修复以适用于 Python
3.2。挑战在于 mailbox 最初是使用文本接口设计的，但电子邮件消息最好用
"bytes" 表示，因为消息的不同部分可能具有不同的编码。

解决方案利用了 "email" 包的二进制支持来解析任意电子邮件消息。此外，解
决方案还需要进行一些 API 更改。

如预期的那样，"mailbox.Mailbox" 对象的 "add()" 方法现在接受二进制输入
。

"StringIO" 和文本文件输入已被弃用。此外，如果使用非 ASCII 字符，字符串
输入将提前失败。此前它会在后续步骤处理电子邮件时失败。

还支持二进制输出。"get_file()" 方法现在以二进制模式返回文件（以前错误
地将文件设置为文本模式）。还有一个新的 "get_bytes()" 方法，它返回与给
定 *key* 对应的 "bytes" 消息表示。

使用旧API的 "get_string()" 方法仍然可以获得非二进制输出，但这种方法并
不非常有用。相反，最好是从 "Message" 对象中提取消息，或者从二进制输入
中加载它们。

（由R. David Murray贡献，Steffen Daode Nurpmeso参与努力，Victor
Stinner在 bpo-9124 中提供初始补丁。）


turtledemo
----------

The demonstration code for the "turtle" module was moved from the
*Demo* directory to main library.  It includes over a dozen sample
scripts with lively displays.  Being on "sys.path", it can now be run
directly from the command-line:

   $ python -m turtledemo

（由Alexander Belopolsky从Demo目录移至主库，见 bpo-10199。）


多线程
======

* The mechanism for serializing execution of concurrently running
  Python threads (generally known as the *GIL* or Global Interpreter
  Lock) has been rewritten.  Among the objectives were more
  predictable switching intervals and reduced overhead due to lock
  contention and the number of ensuing system calls.  The notion of a
  "check interval" to allow thread switches has been abandoned and
  replaced by an absolute duration expressed in seconds.  This
  parameter is tunable through "sys.setswitchinterval()". It currently
  defaults to 5 milliseconds.

  有关该实现的更多详细信息可以从 python-dev 邮件列表消息 中阅读（但需
  注意：该消息中提到的"优先级请求"机制并未被最终采纳）。

  （由 Antoine Pitrou 贡献。）

* 常规和递归锁现在在其 "acquire()" 方法中接受一个可选的 *timeout* 参数
  。（由 Antoine Pitrou 在 bpo-7316 中贡献。）

* 同样，"threading.Semaphore.acquire()" 也增加了一个 *timeout* 参数。
  （由 Torsten Landschoff 在 bpo-850728 中贡献。)

* 在使用 Pthreads 的平台上，常规锁和递归锁的获取操作现在可以被信号中断
  。这意味着Python 程序在获取锁时发生死锁，可以通过反复向该进程发送
  SIGINT 信号（在大多数 shell 中按下 "Ctrl+C"）来成功终止程序。（由
  Reid Kleckner 在 bpo-8844 中贡献。）


性能优化
========

添加了一些小的性能提升：

* Python 的窥孔优化器（peephole optimizer）现在能够识别诸如 "x in {1,
  2, 3}" 这样的模式，将其判定为对常量集合的成员资格测试。优化器会将
  "set" (集合) 重新转换为 "frozenset" (不可变集合) ，并存储这个预先构
  建的常量。

  既然速度开销已不复存在，现在可以放心地开始使用集合表示法来编写成员资
  格测试了。这种写法不仅语义清晰，而且执行高效：

     extension = name.rpartition('.')[2]
     if extension in {'xml', 'html', 'xhtml', 'css'}:
         handle(name)

  （补丁和附加测试由 Dave Malcolm 在 bpo-6690 中贡献）。

* 使用 "pickle" 模块序列化和反序列化数据的速度现在快了几倍。

  （由 Alexandre Vassalotti, Antoine Pitrou 和 Unladen Swallow 团队在
  bpo-9410 和 bpo-3873 中贡献。）

* 在 "list.sort()" 和 "sorted()" 中使用的 Timsort 算法 现在在有 *键函
  数* 的情况下运行更快且使用更少内存。之前，列表的每个元素都会被一个临
  时对象包裹，该对象记住与每个元素关联的键值。现在，键和值的两个数组并
  行排序。这节省了排序包装器消耗的内存，并节省了委托比较所花费的时间。

  （由 Daniel Stutzbach 在 bpo-9915 中提交补丁。）

* JSON 解码性能得到提升，且当同一字符串被用作多个键值时内存消耗降低。
  此外，当 "sort_keys" 参数为 True 时，JSON 编码现会启用 C 语言加速模
  块。

  （由Antoine Pitrou 在 bpo-7451 中贡献，由 Raymond Hettinger 和
  Antoine Pitrou 在 bpo-10314 中贡献。）

* 递归锁（使用 "threading.RLock()" API 创建）现在受益于 C 实现，这使得
  它们与常规锁一样快，并且比之前的纯 Python 实现快 10 到 15 倍。

  （由 Antoine Pitrou 在 bpo-3001 中贡献。）

* The fast-search algorithm in stringlib is now used by the "split()",
  "rsplit()", "splitlines()" and "replace()" methods on "bytes",
  "bytearray" and "str" objects. Likewise, the algorithm is also used
  by "rfind()", "rindex()", "rsplit()" and "rpartition()".

  （由 Florent Xicluna 在 bpo-7622 和 bpo-7462 中提交补丁。）

* 整型转字符串操作现在改为每次处理两个"数字位"，从而减少了除法和取模运
  算的次数。

  （由 Gawain Bolton、Mark Dickinson 和 Victor Stinner 在 bpo-6713 中
  提交。）

There were several other minor optimizations. Set differencing now
runs faster when one operand is much larger than the other (patch by
Andress Bennetts in bpo-8685).  The "array.repeat()" method has a
faster implementation (bpo-1569291 by Alexander Belopolsky). The
"BaseHTTPRequestHandler" has more efficient buffering (bpo-3709 by
Andrew Schaaf).  The "operator.attrgetter()" function has been sped-up
(bpo-10160 by Christos Georgiou).  And "ConfigParser" loads multi-line
arguments a bit faster (bpo-7113 by Łukasz Langa).


Unicode
=======

Python 已更新到 Unicode 6.0.0。此次更新新增了超过 2000 个字符，包括对
手机重要的 emoji 符号。

此外，更新后的标准修改了两个卡纳达文字符（U+0CF1、U+0CF2）和一个新傣仂
数字字符（U+19DA）的字符属性：前者现在可用于标识符，而后者则不再符合标
识符使用要求。更多详细信息请参阅 Unicode字符数据库变更说明。


编解码器
========

添加了对 *cp720* 阿拉伯 DOS 编码的支持（bpo-1616979）。

MBCS 编码不再忽略错误处理程序参数。在默认的严格模式下，当遇到无法解码
的字节序列时，它会引发 "UnicodeDecodeError" 异常；当遇到无法编码的字符
时，会引发 "UnicodeEncodeError" 异常。

多字节字符集编解码器（MBCS codec）在解码时支持 "'strict'" (严格模式)
和 "'ignore'" (忽略模式) 两种错误处理器，在编码时则支持 "'strict'" (严
格模式) 和 "'replace'" (替换模式) 。

若需模拟 Python 3.1 版本的 MBCS 编码行为，应在解码时选用 "'ignore'" (
忽略模式) 错误处理器，而在编码时选用 "'replace'" (替换模式) 错误处理器
。

在 Mac OS X 上，Python 使用 "'utf-8'" 而不是区域设置编码来解码命令行参
数。

默认情况下，"tarfile" 在 Windows 上使用 "'utf-8'" 编码格式 (而不是
"'mbcs'") 并在所有操作系统上使用 "'surrogateescape'" 错误处理器。


文件
====

文档继续得到改进。

* 在长篇幅的章节（如 內建函式）顶部添加了一个快速链接表。以
  "itertools" 为例，这些链接旁边附有速查表风格的摘要表格，无需通读完整
  文档即可快速掌握要点、唤醒记忆。

* 在某些情况下，纯 Python 源代码可以作为文档的有益补充，因此现在许多模
  块都提供了指向最新版本源代码的快速链接。例如，"functools" 模块文档顶
  部有一个快速链接，标记为：

     **源代码** Lib/functools.py.

  （由 Raymond Hettinger 贡献，参见 rationale。）

* 当前文档现包含更多实用示例与技巧指南。特别地，"re" 模块新增了内容详
  尽的正则表达式示例专章 正则表达式例子；同样地，"itertools" 模块也持
  续更新，不断增添新的迭代器工具配方 itertools 配方。

* "datetime" 模块现在有一个纯 Python 的辅助实现。功能没有变化。这只是
  为了提供一个更易读的替代实现。

  （由 Alexander Belopolsky 在 bpo-9528 中贡献。）

* 未维护的 "Demo" 目录已被删除。一些演示被整合到文档中，一些被移动到
  "Tools/demo" 目录，其他的则被完全删除。

  （由 Georg Brandl 在 bpo-7962 中贡献）


IDLE
====

* 格式菜单现在有一个选项，用于通过删除尾部空格来清理源文件。

  （由 Raymond Hettinger 在 bpo-5150 中贡献。）

* Mac OS X 上的 IDLE 现在既支持 Carbon AquaTk 也支持 Cocoa AquaTk。

  （由 Kevin Walzer, Ned Deily 和 Ronald Oussoren 在 bpo-6075 中贡献。
  ）


代码库
======

除了现有的 Subversion 代码仓库位于 https://svn.python.org 外，现在还有
一个 Mercurial 仓库位于 https://hg.python.org/。

在 3.2 版本发布后，计划将 Mercurial 作为主要仓库。这种分布式版本控制系
统应使社区成员更容易创建和共享外部更改集。详见 **PEP 385**。

要学习使用新的版本控制系统，请参阅 Quick Start 或 Guide to Mercurial
Workflows。


构建和 C API 的改变
===================

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

* 现在 *idle*, *pydoc* 和 *2to3* 脚本的安装将在 "make altinstall" 中附
  带特定版本的后缀 (bpo-10679)。

* 访问 Unicode 数据库的 C 函数现在接受并返回完整 Unicode 范围内的字符
  ，即使在窄 Unicode 构建中也是如此（Py_UNICODE_TOLOWER、
  Py_UNICODE_ISDECIMAL 等）。在 Python 中可见的区别是
  "unicodedata.numeric()" 现在为大代码点返回正确的值，而 "repr()" 可能
  有更多字符被视为可打印。

  （由 Bupjoe Lee 报告，Amaury Forgeot D'Arc 修复；参见 bpo-5127 。）

* 计算跳转（computed gotos）现在在支持的编译器（支持情况由配置脚本检测
  ）上默认启用。仍可通过指定 "--without-computed-gotos" 选择性禁用。

  （由 Antoine Pitrou 在 bpo-9203 中贡献。）

* 选项 "--with-wctype-functions" 已被移除。内置的 Unicode 数据库现在用
  于所有函数。

  （由 Amaury Forgeot d'Arc 在 bpo-9210 中贡献。）

* 哈希值现在采用一种新类型 "Py_hash_t" 的值，该类型被定义为与指针具有
  相同的大小。此前，哈希值的类型为 long，在某些 64 位操作系统上，long
  仍然只有 32 位长。得益于这一改进，"set" 和 "dict" 现在可以在使用 64
  位指针的构建版本中容纳超过 "2**32" 个条目（此前，虽然它们能够增长到
  该规模，但其性能会急剧下降）。

  （由 Raymond Hettinger 建议，Benjamin Peterson 实现；参见 bpo-9778。
  ）

* A new macro "Py_VA_COPY" copies the state of the variable argument
  list.  It is equivalent to C99 *va_copy* but available on all Python
  platforms (bpo-2443).

* A new C API function "PySys_SetArgvEx()" allows an embedded
  interpreter to set "sys.argv" without also modifying "sys.path"
  (bpo-5753).

* "PyEval_CallObject" is now only available in macro form.  The
  function declaration, which was kept for backwards compatibility
  reasons, is now removed -- the macro was introduced in 1997
  (bpo-8276).

* 新增函数 "PyLong_AsLongLongAndOverflow()"，它与
  "PyLong_AsLongAndOverflow()" 类似。它们都用于将 Python "int" 转换为
  本地固定宽度类型，并提供检测转换不匹配的情况 (bpo-7767)。

* "PyUnicode_CompareWithASCIIString()" 函数现在在 Python 字符串以
  *NUL* 结尾时返回 *不相等*。

* 新增函数 "PyErr_NewExceptionWithDoc()"，类似于
  "PyErr_NewException()"，但允许指定文档字符串。这使得 C 语言实现的异
  常能够像纯 Python 异常一样具备自文档化能力 (bpo-7033)。

* 当使用 "--with-valgrind" 选项编译时，pymalloc 分配器在 Valgrind 下运
  行时会自动禁用。这提高了在 Valgrind 下运行时的内存泄漏检测能力，同时
  在其他时候利用 pymalloc (bpo-2422)。

* 从 *PyArg_Parse* 函数中移除了 "O?" 格式。该格式不再使用，且从未被文
  档化 (bpo-8837)。

There were a number of other small changes to the C-API.  See the
Misc/NEWS file for a complete list.

Also, there were a number of updates to the Mac OS X build, see
Mac/BuildScript/README.txt for details.  For users running a 32/64-bit
build, there is a known problem with the default Tcl/Tk on Mac OS X
10.6. Accordingly, we recommend installing an updated alternative such
as ActiveState Tcl/Tk 8.5.9. See
https://www.python.org/download/mac/tcltk/ for additional details.


移植到 Python 3.2
=================

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

* The "configparser" module has a number of clean-ups.  The major
  change is to replace the old "ConfigParser" class with long-standing
  preferred alternative "SafeConfigParser".  In addition there are a
  number of smaller incompatibilities:

  * 插值语法现在在 "get()" 和 "set()" 操作中进行验证。在默认的插值方案
    中，只有两个带有百分号的标记是有效的："%(name)s" 和 "%%"，后者是转
    义后的百分号。

  * "set()" 和 "add_section()" 方法现在验证值是否为实际的字符串。以前
    ，可能会无意引入不支持的类型。

  * 来自单个源的重复节或选项现在会引发 "DuplicateSectionError" 或
    "DuplicateOptionError"。此前，重复项会默默地覆盖先前的条目。

  * 内联注释现在默认禁用，因此现在可以安全地在值中使用 **;** 字符。

  * 注释现在可以缩进。因此，为了在多行值的行首出现 **;** 或 **#**，必
    须进行插值。这样可以防止值中的注释前缀字符被误认为是注释。

  * """" 现在是一个有效值，不再自动转换为空字符串。对于空字符串，请在
    行中使用 ""option =""。

* The "nntplib" module was reworked extensively, meaning that its APIs
  are often incompatible with the 3.1 APIs.

* "bytearray" 对象不能再用作文件名；相反，它们应该转换为 "bytes"。

* The "array.tostring()" and "array.fromstring()" have been renamed to
  "array.tobytes()" and "array.frombytes()" for clarity.  The old
  names have been deprecated. (See bpo-8990.)

* "PyArg_Parse*()" 函数:

  * "t#" 格式已被移除：改用 "s#" 或 "s*"

  * "w" 和 "w#" 格式已被移除：改用 "w*"

* The "PyCObject" type, deprecated in 3.1, has been removed.  To wrap
  opaque C pointers in Python objects, the "PyCapsule" API should be
  used instead; the new type has a well-defined interface for passing
  typing safety information and a less complicated signature for
  calling a destructor.

* The "sys.setfilesystemencoding()" function was removed because it
  had a flawed design.

* "random.seed()" 函数和方法现在使用 sha512 哈希函数对字符串种子进行加
  盐。为了访问以前版本的 *seed* 以重现 Python 3.1 序列，将 *version*
  参数设置为 *1*，即 "random.seed(s, version=1)"。

* The previously deprecated "string.maketrans()" function has been
  removed in favor of the static methods "bytes.maketrans()" and
  "bytearray.maketrans()".  This change solves the confusion around
  which types were supported by the "string" module.  Now, "str",
  "bytes", and "bytearray" each have their own **maketrans** and
  **translate** methods with intermediate translation tables of the
  appropriate type.

  （由Georg Brandl在 bpo-5675 中贡献）

* The previously deprecated "contextlib.nested()" function has been
  removed in favor of a plain "with" statement which can accept
  multiple context managers.  The latter technique is faster (because
  it is built-in), and it does a better job finalizing multiple
  context managers when one of them raises an exception:

     with open('mylog.txt') as infile, open('a.out', 'w') as outfile:
         for line in infile:
             if '<critical>' in line:
                 outfile.write(line)

  （由 Georg Brandl 和 Mattias Brändström 贡献; appspot issue 53094。
  ）

* "struct.pack()" 现在只允许使用字节类型（bytes）作为 "s" 字符串打包代
  码的参数。此前，该函数会接受文本类型（text）参数，并隐式地使用 UTF-8
  编码将其转换为字节类型。这种做法存在两个问题：一是它对正确的编码方式
  做了预设假设；二是在将变长编码写入结构的固定长度字段时可能会导致失败
  。

  类似于 "struct.pack('<6sHHBBB', 'GIF87a', x, y)" 的代码应重写为使用
  字节串而不是文本，即 "struct.pack('<6sHHBBB', b'GIF87a', x, y)"。

  （由 David Beazley 发现，并由 Victor Stinner 修复；参见 bpo-10783。
  ）

* "xml.etree.ElementTree" 类在解析失败时现在会抛出
  "xml.etree.ElementTree.ParseError"。之前，它会抛出
  "xml.parsers.expat.ExpatError"。

* 新的、更长的浮点数 "str()" 输出格式可能会导致依赖旧输出格式的
  doctest 测试用例失效。

* 在 "subprocess.Popen" 中，*close_fds* 的默认值在 Unix 上现在为
  "True"；在 Windows 上，如果三个标准流均设置为 "None"，则为 "True"，
  否则为 "False"。之前，*close_fds* 默认总是 "False"，这会导致打开的文
  件描述符泄露到子进程中，产生难以解决的错误或竞争条件。

* 对旧式 HTTP 0.9 的支持已从 "urllib.request" 和 "http.client" 中移除
  。 此项支持仍然存在于服务器端（在 "http.server" 中）。

  （由 Antoine Pitrou 在 bpo-10711 中贡献。）

* 超时模式下的 SSL 套接字现在如发生超时则会引发 "socket.timeout"，而不
  是一般性的 "SSLError"。

  （由 Antoine Pitrou 在 bpo-10272 中贡献。）

* The misleading functions "PyEval_AcquireLock()" and
  "PyEval_ReleaseLock()" have been officially deprecated.  The thread-
  state aware APIs (such as "PyEval_SaveThread()" and
  "PyEval_RestoreThread()") should be used instead.

* Due to security risks, "asyncore.handle_accept()" has been
  deprecated, and a new function, "asyncore.handle_accepted()", was
  added to replace it.

  （由 Giampaolo Rodola 在 bpo-6706 中贡献。）

* 由于新的 *GIL* 实现，"PyEval_InitThreads()" 将不再能在
  "Py_Initialize()" 之前被调用。
