Python 3.2 有什么新变化¶
- 作者
Raymond Hettinger(译者:wh2099 at outlook dot com)
This article explains the new features in Python 3.2 as compared to 3.1. 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
PEP 由 Martin von Löwis 撰写
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 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 - 基于字典的日志配置
PEP 由 Vinay Sajip 撰写
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 - 异步执行指令
PEP 由 Brian Quinlan 撰写
使用线程并行 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
andPyPycLoader
, have been deprecated (instructions on how to stay Python 3.1 compatible are included with the documentation).
参见
- PEP 3147 - PYC 仓库目录
PEP 由 Barry Warsaw 撰写
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 文件
PEP 由 Barry Warsaw 撰写
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. Thestart_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
PEP 由 Phillip Eby 撰写
其他语言特性修改¶
对Python 语言核心进行的小改动:
format()
函数和str.format()
方法的字符串格式化功能为格式字符 # 新增了能力。此前,对于二进制、八进制或十六进制的整数,该字符会使输出分别带有 '0b'、'0o' 或 '0x' 前缀。现在,它还能处理浮点数、复数和 Decimal 类型,确保输出始终包含小数点——即使后续没有数字跟随。>>> format(20, '#o') '0o24' >>> format(12.34, '#5.0f') ' 12.'
(由 Mark Dickinson 建议,Eric Smith 在 bpo-7094 中实现。)
There is also a new
str.format_map()
method that extends the capabilities of the existingstr.format()
method by accepting arbitrary mapping objects. This new method makes it possible to use string formatting with any of Python's many dictionary-like objects such asdefaultdict
,Shelf
,ConfigParser
, ordbm
. It is also useful with customdict
subclasses that normalize keys before look-up or that supply a__missing__()
method for unknown keys:>>> 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 thesys.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 callinggetattr()
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 catchAttributeError
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 arelease()
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 byos.stat()
,time.gmtime()
, andsys.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 thegc.garbage
list isn't empty, and ifgc.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 thecollections.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 thansys.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 地址。
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.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)
在这个示例中,屏障执行了一个更健壮的规则。如果某些选举站在午夜前没有完成,屏障将超时,选票将被封存并放入队列中以供后续处理。
See Barrier Synchronization Patterns for more examples of how barriers can be used in parallel computing. Also, there is a simple but thorough explanation of barriers in The Little Book of Semaphores, section 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 isTrue
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 thattime.accept2dyear
be set toFalse
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, thetime.asctime()
function will accept any year that fits in a C int, while thetime.mktime()
andtime.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'>
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 > 2 && x < 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), andssl.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 模块有许多改进,支持包的测试发现、在交互式提示符下更容易进行实验、新的测试用例方法、改进的测试失败诊断消息以及更好的方法名称。
The command-line call
python -m unittest
can now accept file paths instead of module names for running specific tests (bpo-10620). The new test discovery can find tests within packages, locating any test importable from the top-level directory. The top-level directory can be specified with the -t option, a pattern for matching files with-p
, and a directory to start discovery with-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 forassertRegexpMatches()
which was misnamed because the test usesre.search()
, notre.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 there
module, and it has unambiguous camel-casing.(由 Raymond Hettinger 贡献并由 Ezio Melotti 实现。)
为了提高一致性,一些长期存在的方法别名正在被弃用,转而使用首选名称:
旧名称
首选名称
assert_()
assertEquals()
assertNotEquals()
assertAlmostEquals()
assertNotAlmostEquals()
Likewise, the
TestCase.fail*
methods deprecated in Python 3.1 are expected to be removed in Python 3.3. Also see the 一些已被弃用的别名 section in theunittest
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 likeTestCase().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¶
The pydoc
module now provides a much-improved Web server interface, as
well as a new command-line option -b
to automatically open a browser window
to display that server:
$ 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()
andreplace()
methods onbytes
,bytearray
andstr
objects. Likewise, the algorithm is also used byrfind()
,rindex()
,rsplit()
andrpartition()
.整型转字符串操作现在改为每次处理两个"数字位",从而减少了除法和取模运算的次数。
(由 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 has been updated to Unicode 6.0.0. The update to the standard adds over 2,000 new characters including emoji symbols which are important for mobile phones.
In addition, the updated standard has altered the character properties for two Kannada characters (U+0CF1, U+0CF2) and one New Tai Lue numeric character (U+19DA), making the former eligible for use in identifiers while disqualifying the latter. For more information, see Unicode Character Database Changes.
编解码器¶
添加了对 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¶
代码库¶
In addition to the existing Subversion code repository at http://svn.python.org there is now a Mercurial repository at 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 setsys.argv
without also modifyingsys.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()
类似。它们都用于将 Pythonint
转换为本地固定宽度类型,并提供检测转换不匹配的情况 (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 oldConfigParser
class with long-standing preferred alternativeSafeConfigParser
. 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.The
array.tostring()
andarray.fromstring()
have been renamed toarray.tobytes()
andarray.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, thePyCapsule
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 methodsbytes.maketrans()
andbytearray.maketrans()
. This change solves the confusion around which types were supported by thestring
module. Now,str
,bytes
, andbytearray
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 plainwith
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()
andPyEval_ReleaseLock()
have been officially deprecated. The thread-state aware APIs (such asPyEval_SaveThread()
andPyEval_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()
之前被调用。