Python 3.8 有什么新�化¶

编者:

Raymond Hettinger(译者:wh2099 at outlook dot com)

这篇文章介�了 Python 3.8 相比 3.7 增加的新特性。 Python 3.8 �布于 2019 年 10 月 14 日。 更详细的信���阅 更新日志。

摘� -- �布�点¶

新的特性¶

赋值表达�¶

新增的语法 := �在表达�内部为��赋值。 它被昵称为“海象�算符�因为它很�是 海象的眼�和长牙。

在这个示例中,赋值表达��以��调用 len() 两次:

if (n := len(a)) > 10:
    print(f"List is too long ({n} elements, expected <= 10)")

类似的益处还�出现在正则表达�匹�中需�使用两次匹�对象的情况中,一次检测用于匹�是��生,�一次用于���分组:

discount = 0.0
if (mo := re.search(r'(\d+)% discount', advertisement)):
    discount = float(mo.group(1)) / 100.0

此�算符也适用于�� while 循环计算一个值�检测循环是�终止,而�一个值�在循环体中�次被使用的情况:

# Loop over fixed length blocks
while (block := f.read(256)) != '':
    process(block)

�一个值得介�的用例出现于列表推导�中,在筛选�件中计算一个值,而�一个值�在表达�中需�被使用:

[clean_name.title() for name in names
 if (clean_name := normalize('NFC', name)) in allowed_names]

请尽�将海象�算符的使用�制在清晰的场�中,以�低��性并���读性。

请�阅 PEP 572 了解详情。

(由 Morehouse 在 bpo-35224 中贡献。)

仅��置形�¶

新增了一个函数形�语法 / 用�指明�些函数形�必须作为�置�数而��作为关键字�数。 这�标记语法与通过 help() 显示的使用 Larry Hastings 的 Argument Clinic 工具所标记的 C 函数相�。

在下�的例�中,形� a 和 b 为仅��置形�,c 或 d �以是�置形�或关键字形�,而 e 或 f �求为关键字形�:

def f(a, b, /, c, d, *, e, f):
    print(a, b, c, d, e, f)

以下�为�法的调用:

f(10, 20, 30, d=40, e=50, f=60)

但是,以下�为��法的调用:

f(10, b=20, c=30, d=40, e=50, f=60)   # b cannot be a keyword argument
f(10, 20, 30, 40, 50, f=60)           # e must be a keyword argument

这�标记形�的一个用例是它�许纯 Python 函数完整模拟现有的用 C 代�编写的函数的行为。 例如,内置的 divmod() 函数�接�关键字�数:

def divmod(a, b, /):
    "Emulate the built in divmod() function"
    return (a // b, a % b)

�一个用例是在�需�形��称时排除关键字�数。 例如,内置的 len() 函数的签�为 len(obj, /)。 这�以排除如下这�笨拙的调用形�:

len(obj='hello')  # The "obj" keyword argument impairs readability

�一个益处是将形�标记为仅��置形�将�许在未�修改形��而�会破�客户的代�。 例如,在 statistics 模�中,形�� dist 在未��能被修改。 这使得以下函数�述�为�能:

def quantiles(dist, /, *, n=4, method='exclusive')
    ...

由于在 / 左侧的形��会被公开为�用关键字,其他形����在 **kwargs 中使用:

>>> def f(a, b, /, **kwargs):
...     print(a, b, kwargs)
...
>>> f(10, 20, a=1, b=2, c=3)         # a and b are used in two ways
10 20 {'a': 1, 'b': 2, 'c': 3}

这�大地简化了需�接�任�关键字�数的函数和方法的实现。 例如,以下是一段摘自 collections 模�的代�:

class Counter(dict):

    def __init__(self, iterable=None, /, **kwds):
        # Note "iterable" is a possible keyword argument

请�阅 PEP 570 了解详情。

(由 Pablo Galindo 在 bpo-36540 中贡献。)

用于已编译字节�文件的并行文件系统缓存¶

新增的 PYTHONPYCACHEPREFIX 设置 (也�使用 -X pycache_prefix) �将��的字节�缓存�置为使用�独的并行文件系统树,而�是默认的�个�代�目录下的 __pycache__ �目录。

缓存的�置会在 sys.pycache_prefix 中报告 (None 表示默认�置� __pycache__ �目录)。

(由 Carl Meyer 在 bpo-33499 中贡献。)

调试构建使用与�布构建相�的 ABI¶

Python 现在�论是以�布模�还是调试模�进行构建都将使用相�的 ABI。 在 Unix 上,当 Python 以调试模�构建时,现在将�以加载以�布模�构建的 C 扩展和使用稳定版 ABI 构建的 C 扩展。

�布编译版和 调试编译版 现在都是 ABI 兼容的:定义 Py_DEBUG ��会�应用 Py_TRACE_REFS �,它引入 了唯一的 ABI �兼容性。 Py_TRACE_REFS �添加了 sys.getobjects() 函数和 PYTHONDUMPREFS 环境��,它�以使用新的 ./configure --with-trace-refs 编译选项�设置。 (由 Victor Stinner 在 bpo-36465 中贡献。)

在 Unix 上,C 扩展�会�被链接到 libpython,但 Android 和 Cygwin 例外。 现在��链接的 Python 将�以加载使用共享库 Python 构建的 C 扩展。 (由 Victor Stinner 在 bpo-21536 中贡献。)

在 Unix 上,当 Python 以调试模�构建时,导入�作现在也会查找在�布模�下编译的 C 扩展以�使用稳定版 ABI 编译的 C 扩展。 (由 Victor Stinner 在 bpo-36722 中贡献。)

�将 Python 嵌入到一个应用中,必须将新增的 --embed 选项传给 python3-config --libs --embed 以获得 -lpython3.8 (将应用链接到 libpython)。 ��时支� 3.8 和旧版本,请先�试 python3-config --libs --embed 并在此命令失败时回退到 python3-config --libs (��带 --embed)。

增加一个 pkg-config python-3.8-embed 模�用�将 Python 嵌入到一个应用中: pkg-config python-3.8-embed --libs 包� -lpython3.8。 ��时支� 3.8 和旧版本,请先�试 pkg-config python-X.Y-embed --libs 并在此命令失败时回退到 pkg-config python-X.Y --libs (��带 --embed) (请将 X.Y 替�为 Python 版本�)。

�一方�,pkg-config python3.8 --libs ��包� -lpython3.8。 C 扩展��被链接到 libpython (但 Android 和 Cygwin 例外,这两者的情况由脚本处�);此改�是故�被设为�下�兼容的。 (由 Victor Stinner 在 bpo-36721 中贡献。)

f-字符串支� = 用于自动记录表达�和调试文档¶

增加 = 说明符用于 f-string。 形�为 f'{expr=}' 的 f-字符串将扩展表示为表达�文本,加一个等于�,�加表达�的求值结果。 例如:

>>> user = 'eric_idle'
>>> member_since = date(1975, 7, 31)
>>> f'{user=} {member_since=}'
"user='eric_idle' member_since=datetime.date(1975, 7, 31)"

通常的 f-字符串格�说明符 �许更细致地控制所�显示的表达�结果:

>>> delta = date.today() - member_since
>>> f'{user=!s}  {delta.days=:,d}'
'user=eric_idle  delta.days=16,075'

= 说明符将输出整个表达�,以便详细演示计算过程:

>>> print(f'{theta=}  {cos(radians(theta))=:.3f}')
theta=30  cos(radians(theta))=0.866

(由 Eric V. Smith 和 Larry Hastings 在 bpo-36817 中贡献。)

PEP 578: Python �行时审核钩�¶

此 PEP 添加了审核钩�和已验�开放钩�。 两者在 Python 与本机代�中��用。�许以纯 Python 代�编写的应用和框架利用�外的通知,�时�许嵌入开�人员或系统管�员部署始终�用审核的 Python 版本。

请�阅 PEP 578 了解详情。

PEP 587: Python �始化�置¶

PEP 587 增加了一个新的 C API 用��置 Python �始化,�供对整个�置过程的更细致控制以�更好的错误报告。

新的结构:

新的函数:

此 PEP 还为这些内部结构添加了 _PyRuntimeState.preconfig (PyPreConfig 类型) 和 PyInterpreterState.config (PyConfig 类型) 字段。 PyInterpreterState.config �为新的引用�置,替代全局�置��和其他�有��。

请�阅 Python �始化�置 获�详细文档。

请�阅 PEP 587 了解详情。

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

PEP 590: Vectorcall: 用于 CPython 的快速调用�议¶

将 Vectorcall �议 添加到 Python/C API。 它的目标是对已被应用于多个类的现有优先进行正�化。 任何实现了�调用对象的 ��类型 ��使用此�议。

此特性目�为暂定状�,计划在 Python 3.9 将其完全公开。

请�阅 PEP 590 了解详情。

(由 Jeroen Demeyer, Mark Shannon 和 Petr Viktorin 在 bpo-36974 中贡献。)

具有外部数�缓冲区的 pickle �议 5¶

当使用 pickle 在 Python 进程间传输大�数�以充分�挥多核或多机处�的优势时,�常��一点是通过�少内存拷��优化传输效率,并�能应用一些定制技巧例如针对特定数�的压缩。

pickle �议 5 引入了对于外部缓冲区的支�,这样 PEP 3118 兼容的数��以与主 pickle �分开进行传输,这是由通信层�确定的。

请�阅 PEP 574 了解详情。

(由 Antoine Pitrou 在 bpo-36785 中贡献。)

其他语言特性修改¶

  • 在之å‰�版本中 continue 语å�¥ä¸�å…�许在 finally å­�å�¥ä¸­ä½¿ç”¨ï¼Œè¿™æ˜¯å› ä¸ºå…·ä½“实现存在一个问题。 在 Python 3.8 中此é™�制已被å�–消。 (由 Serhiy Storchaka 在 bpo-32489 中贡献。)

  • bool, int å’Œ fractions.Fraction 类型现在都有一个 as_integer_ratio() 方法,与 float å’Œ decimal.Decimal 中的已有方法类似。 这个微å°�çš„ API 扩展使得 numerator, denominator = x.as_integer_ratio() 这样的写法在多ç§�数字类型上通用æˆ�为å�¯èƒ½ã€‚ (由 Lisa Roach 在 bpo-33073 å’Œ Raymond Hettinger 在 bpo-37819 中贡献。)

  • int, float å’Œ complex 的构造器现在会使用 __index__() 特殊方法,如果该方法å�¯ç”¨è€Œå¯¹åº”的方法 method __int__(), __float__() 或 __complex__() 方法ä¸�å�¯ç”¨çš„è¯�。 (由 Serhiy Storchaka 在 bpo-20092 中贡献。)

  • 在 正则表达å¼�: 中添加了对 \N{name} 转义ç �的支æŒ�:

    >>> notice = 'Copyright © 2019'
    >>> copyright_year_pattern = re.compile(r'\N{copyright sign}\s*(\d{4})')
    >>> int(copyright_year_pattern.search(notice).group(1))
    2019
    

    (由 Jonathan Eunice 和 Serhiy Storchaka 在 bpo-30688 中贡献。)

  • 现在 dict å’Œ dictview å�¯ä»¥ä½¿ç”¨ reversed() 按æ�’入顺åº�å��å�‘迭代。 (由 Rémi Lapeyre 在 bpo-33462 中贡献。)

  • 在函数调用中å…�许使用的关键字å��称语法å�—到进一步的é™�制。 特别地,f((keyword)=arg) ä¸�å†�被å…�许。 关键字å�‚数赋值形å¼�的左侧ç»�ä¸�å…�许一般标识符以外的其他内容。 (由 Benjamin Peterson 在 bpo-34641 中贡献。)

  • 在 yield å’Œ return 语å�¥ä¸­çš„一般å�¯è¿­ä»£å¯¹è±¡è§£åŒ…ä¸�å†�è¦�求加圆括å�·ã€‚ 这使得 yield å’Œ return 的语法与正常的赋值语法更为一致:

    >>> def parse(family):
            lastname, *members = family.split()
            return lastname.upper(), *members
    
    >>> parse('simpsons homer marge bart lisa maggie')
    ('SIMPSONS', 'homer', 'marge', 'bart', 'lisa', 'maggie')
    

    (由 David Cuthbert 和 Jordan Chapman 在 bpo-32117 中贡献。)

  • 当类似 [(10, 20) (30, 40)] 这样在代ç �中少了一个逗å�·æ—¶ï¼Œç¼–译器将显示 SyntaxWarning 并附带更有帮助的æ��示。 这相比原æ�¥ç”¨ TypeError æ�¥æ��示第一个元组是ä¸�å�¯è°ƒç”¨çš„æ›´å®¹æ˜“被ç�†è§£ã€‚ (由 Serhiy Storchaka 在 bpo-15248 中贡献。)

  • datetime.date 或 datetime.datetime å’Œ datetime.timedelta 对象之间的算术è¿�算现在将返回相应å­�类的实例而ä¸�是基类的实例。 这也会影å“�到在具体实现中(直接或间接地)使用了 datetime.timedelta 算术è¿�算的返回类型,例如 astimezone()。 (由 Paul Ganssle 在 bpo-32417 中贡献。)

  • 当 Python 解释器通过 Ctrl-C (SIGINT) 被中断并且所产生的 KeyboardInterrupt 异常未被æ�•获,Python 进程现在会通过一个 SIGINT ä¿¡å�·æˆ–是使得å�‘起调用的进程能检测到它是由 Ctrl-C æ“�作æ�€æ­»çš„æ­£ç¡®é€€å‡ºä»£ç �æ�¥é€€å‡ºã€‚ POSIX å’Œ Windows 上的终端会相应地使用此代ç �在交互å¼�会è¯�中终止脚本。 (由 Google çš„ Gregory P. Smith 在 bpo-1054041 中贡献。)

  • æŸ�些高级编程风格è¦�求为现有的函数更新 types.CodeType 对象。 由于代ç �对象是ä¸�å�¯å�˜çš„,需è¦�基于现有代ç �对象模型创建一个新的代ç �对象。 使用 19 个形å�‚将会相当ç¹�ç��。 现在,新的 replace() 方法使得通过少é‡�修改的形å�‚创建克隆对象æˆ�为å�¯èƒ½ã€‚

    下�是一个修改 statistics.mean() 函数�防止 data 形�被用作关键字�数的例�:

    >>> from statistics import mean
    >>> mean(data=[10, 20, 90])
    40
    >>> mean.__code__ = mean.__code__.replace(co_posonlyargcount=1)
    >>> mean(data=[10, 20, 90])
    Traceback (most recent call last):
      ...
    TypeError: mean() got some positional-only arguments passed as keyword arguments: 'data'
    

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

  • 对于整数,现在 pow() 函数的三å�‚æ•°å½¢å¼�在底数与模数ä¸�å�¯çº¦çš„æƒ…况下å…�许指数为负值。 éš�å�Žå®ƒä¼šåœ¨æŒ‡æ•°ä¸º -1 时计算底数的模乘逆元,并对其他负指数计算å��模的适当幂次。 例如,è¦�计算 38 模 137 çš„ 模乘逆元 则å�¯å†™ä¸º:

    >>> pow(38, -1, 137)
    119
    >>> 119 * 38 % 137
    1
    

    模乘逆元在求解 线性丢番图方程 会被用到。 例如,想�求出 4258� + 147� = 369 的整数解,首先应�写为 4258� ≡ 369 (mod 147) 然�求解:

    >>> x = 369 * pow(4258, -1, 147) % 147
    >>> y = (4258 * x - 369) // -147
    >>> 4258 * x + 147 * y
    369
    

    (由 Mark Dickinson 在 bpo-36027 中贡献。)

  • 字典推导å¼�已与字典字é�¢å€¼å®žçްå�Œæ­¥ï¼Œä¼šå…ˆè®¡ç®—é”®å†�计算值:

    >>> # Dict comprehension
    >>> cast = {input('role? '): input('actor? ') for i in range(2)}
    role? King Arthur
    actor? Chapman
    role? Black Knight
    actor? Cleese
    
    >>> # Dict literal
    >>> cast = {input('role? '): input('actor? ')}
    role? Sir Robin
    actor? Eric Idle
    

    对执行顺�的��对赋值表达��说很有用,因为在键表达�中赋值的��将�在值表达�中被使用:

    >>> names = ['Martin von Löwis', '�ukasz Langa', 'Walter Dörwald']
    >>> {(n := normalize('NFC', name)).casefold() : n for name in names}
    {'martin von löwis': 'Martin von Löwis',
     'łukasz langa': '�ukasz Langa',
     'walter dörwald': 'Walter Dörwald'}
    

    (由 Jörn Heissler 在 bpo-35224 中贡献。)

  • object.__reduce__() 方法现在å�¯è¿”回长度为二至六个元素的元组。 之å‰�的上é™�为五个。 新增的第六个å�¯é€‰å…ƒç´ æ˜¯ç­¾å��为 (obj, state) çš„å�¯è°ƒç”¨å¯¹è±¡ã€‚ 这样就å…�许直接控制特定对象的状æ€�更新。 如果元素值ä¸�为 None,该å�¯è°ƒç”¨å¯¹è±¡å°†ä¼˜å…ˆäºŽå¯¹è±¡çš„ __setstate__() 方法。 (由 Pierre Glaser å’Œ Olivier Grisel 在 bpo-35900 中贡献。)

新增模�¶

  • 新增的 importlib.metadata 模å�—æ��供了从第三方包读å�–元数æ�®çš„(临时)支æŒ�。 例如,它å�¯ä»¥æ��å�–一个已安装软件包的版本å�·ã€�å…¥å�£ç‚¹åˆ—表等等:

    >>> # Note following example requires that the popular "requests"
    >>> # package has been installed.
    >>>
    >>> from importlib.metadata import version, requires, files
    >>> version('requests')
    '2.22.0'
    >>> list(requires('requests'))
    ['chardet (<3.1.0,>=3.0.2)']
    >>> list(files('requests'))[:5]
    [PackagePath('requests-2.22.0.dist-info/INSTALLER'),
     PackagePath('requests-2.22.0.dist-info/LICENSE'),
     PackagePath('requests-2.22.0.dist-info/METADATA'),
     PackagePath('requests-2.22.0.dist-info/RECORD'),
     PackagePath('requests-2.22.0.dist-info/WHEEL')]
    

    (由 Barry Warsaw 和 Jason R. Coombs 在 bpo-34632 中贡献)。

改进的模�¶

ast¶

AST 节点现在具有 end_lineno 和 end_col_offset 属性,它们给出节点结�的精确�置。 (这�适用于具有 lineno 和 col_offset 属性的节点。)

新增函数 ast.get_source_segment() 返回指定 AST 节点的�代�。

(由 Ivan Levkivskyi 在 bpo-33416 中贡献。)

ast.parse() 函数具有一些新的旗标:

  • type_comments=True 导致其返回与特定 AST 节点相关è�”çš„ PEP 484 å’Œ PEP 526 类型注释文本;

  • mode='func_type' å�¯è¢«ç”¨äºŽè§£æž� PEP 484 "ç­¾å��类型注释" (为函数定义 AST 节点而返回)ï¼›

  • feature_version=(3, N) å…�许指定一个更早的 Python 3 版本。 例如,feature_version=(3, 4) 将把 async å’Œ await 视为é�žä¿�留字。

(由 Guido van Rossum 在 bpo-35766 中贡献。)

asyncio¶

asyncio.run() 已�从暂定状�晋级为稳定 API。 此函数�被用于执行一个 coroutine 并返回结果,�时自动管�事件循环。 例如:

import asyncio

async def main():
    await asyncio.sleep(0)
    return 42

asyncio.run(main())

这 大致 等价于:

import asyncio

async def main():
    await asyncio.sleep(0)
    return 42

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
    loop.run_until_complete(main())
finally:
    asyncio.set_event_loop(None)
    loop.close()

实际的实现�更��许多。 因此 asyncio.run() 应该作为�行 asyncio 程�的首选方�。

(由 Yury Selivanov 在 bpo-32314 中贡献。)

�行 python -m asyncio 将�动一个原生异步 REPL。 这�许快速体验具有最高层级 await 的代�。 这时��需�直接调用 asyncio.run(),因为此�作会在�次�起调用时产生一个新事件循环:

$ python -m asyncio
asyncio REPL 3.8.0
Use "await" directly instead of "asyncio.run()".
Type "help", "copyright", "credits" or "license" for more information.
>>> import asyncio
>>> await asyncio.sleep(10, result='hello')
hello

(由 Yury Selivanov 在 bpo-37028 中贡献。)

异常 asyncio.CancelledError 现在继承自 BaseException 而�是 Exception 并且��继承自 concurrent.futures.CancelledError。 (由 Yury Selivanov 在 bpo-32528 中贡献。)

在 Windows 上,现在默认的事件循环为 ProactorEventLoop。 (由 Victor Stinner 在 bpo-34687 中贡献。)

ProactorEventLoop 现在也支� UDP。 (由 Adam Meily 和 Andrew Svetlov 在 bpo-29883 中贡献。)

ProactorEventLoop 现在�通过 KeyboardInterrupt ("CTRL+C") �中断。 (由 Vladimir Matveev 在 bpo-23057 中贡献。)

添加了 asyncio.Task.get_coro() 用�获� asyncio.Task 中的已包装�程。 (由 Alex Grönholm 在 bpo-36999 中贡献。)

asyncio 任务现在�以被命�,或者是通过将 name 关键字�数传给 asyncio.create_task() 或 create_task() 事件循环方法,或者是通过在任务对象上调用 set_name() 方法。 任务�称在 asyncio.Task 的 repr() 输出中��,并且还�以使用 get_name() 方法�获�。 (由 Alex Grönholm 在 bpo-34270 中贡献。)

将对 Happy Eyeballs 的支�添加到 asyncio.loop.create_connection()。 �指定此行为,已增加了两个新的形�: happy_eyeballs_delay 和 interleave。 Happy Eyeballs 算法���支� IPv4 和 IPv6 的应用的�应速度,具体�法是�试�时使用两者进行连接。 (由 twisteroid ambassador 在 bpo-33530 中贡献。)

builtins¶

内置的 compile() 已改进为�接� ast.PyCF_ALLOW_TOP_LEVEL_AWAIT 旗标。 当传入此新旗标时,compile() 将�许通常被视为无效语法的最高层级 await, async for 和 async with 构造。 此�将�返回带有 CO_COROUTINE 旗标的异步代�对象。 (由 Matthias Bussonnier 在 bpo-34616 中贡献。)

collections¶

collections.namedtuple() 的 _asdict() 方法现在将返回 dict 而�是 collections.OrderedDict。 此项更改是由于普通字典自 Python 3.7 起已��具有确定的元素顺�。 如果还需� OrderedDict 的�外特性,建议的解决方案是将结果转�为需�的类型: OrderedDict(nt._asdict())。 (由 Raymond Hettinger 在 bpo-35864 中贡献。)

cProfile¶

cProfile.Profile 类现在�被用作上下文管�器。 在�行时对一个代��实现性能分�:

import cProfile

with cProfile.Profile() as profiler:
      # code to be profiled
      ...

(由 Scott Sanderson 在 bpo-29235 中贡献。)

csv¶

csv.DictReader 现在将返回 dict 而�是 collections.OrderedDict。 此工具现在会更快速且消耗更少内存�时�然�留字段顺�。 (由 Michael Selik 在 bpo-34003 中贡献。)

curses¶

添加了一个新��用于�存下层 ncurses 库的结构版信�: ncurses_version。 (由 Serhiy Storchaka 在 bpo-31680 中贡献。)

ctypes¶

在 Windows 上,CDLL �其�类现在接� winmode 形��指定用于底层 LoadLibraryEx 调用的旗标。 默认旗标被设为仅加载�自�信任�置的 DLL �赖项,包括 DLL 的存放路径(如果加载�始 DLL 时使用了完整或部分路径)以�通过 add_dll_directory() 添加的路径。 (由 Steve Dower 在 bpo-36085 中贡献。)

datetime¶

添加了新的替代构造器 datetime.date.fromisocalendar() 和 datetime.datetime.fromisocalendar(),它们分别基于 ISO 年份�周��和周内日���构造 date 和 datetime 对象;这两者分别是其所对应类中 isocalendar 方法的逆�作。 (由 Paul Ganssle 在 bpo-36004 中贡献。)

functools¶

functools.lru_cache() 现在�直接作为装饰器而�是作为返回装饰器的函数。 因此这两�写法现在都被支�:

@lru_cache
def f(x):
    ...

@lru_cache(maxsize=256)
def f(x):
    ...

(由 Raymond Hettinger 在 bpo-36772 中贡献。)

添加了新的 functools.cached_property() 装饰器,用于在实例生命周期内缓存的已计算特�属性。

import functools
import statistics

class Dataset:
   def __init__(self, sequence_of_numbers):
      self.data = sequence_of_numbers

   @functools.cached_property
   def variance(self):
      return statistics.variance(self.data)

(由 Carl Meyer 在 bpo-21145 中贡献)

添加了新的 functools.singledispatchmethod() 装饰器�使用 single dispatch 将方法转�为 泛型函数:

from functools import singledispatchmethod
from contextlib import suppress

class TaskManager:

    def __init__(self, tasks):
        self.tasks = list(tasks)

    @singledispatchmethod
    def discard(self, value):
        with suppress(ValueError):
            self.tasks.remove(value)

    @discard.register(list)
    def _(self, tasks):
        targets = set(tasks)
        self.tasks = [x for x in self.tasks if x not in targets]

(由 Ethan Smith 在 bpo-32380 中贡献)

gc¶

get_objects() 现在能接�一个�选的 generation 形��指定一个用于获�对象的生�器。 (由 Pablo Galindo 在 bpo-36016 中贡献。)

gettext¶

添加了 pgettext() �其�化形�。 (由 Franz Glasner, Éric Araujo 和 Cheryl Sabella 在 bpo-2504 中贡献。)

gzip¶

添加 mtime 形�到 gzip.compress() 用于��现的输出。 (由 Guo Ci Teo 在 bpo-34898 中贡献。)

对于特定类型的无效或已�� gzip 文件现在将引� BadGzipFile 而�是 OSError。 (由 Filip Gruszczyński, Michele Orrù 和 Zackery Spytz 在 bpo-6584 中贡献。)

IDLE 与 idlelib¶

超过 N 行(默认值为 50)的输出将被折�为一个按钮。 N �以在 Settings 对�框的 General 页的 PyShell 部分中进行修改。 数�较少但是超长的行�以通过在输出上�击�折�。 被折�的输出�通过�击按钮�展开,或是通过�击按钮�放入剪贴�或是�独的窗�。 (由 Tal Einat 在 bpo-1529353 中贡献。)

在 Run ��中增加了 "Run Customized" 以使用自定义设置��行模�。 输入的任何命令行�数都会被加入 sys.argv。 它们在下次自定义�行时会�次显示在窗体中。 用户也�以�用通常的 Shell 主模���。 (由 Cheryl Sabella, Terry Jan Reedy 等人在 bpo-5680 和 bpo-37627 中贡献。)

在 IDLE 编辑器窗�中增加了�选的行�。 窗�打开时默认�显示行�,除�在�置对�框的 General 选项�中特别设置。 已打开窗�中的行��以在 Options ��中显示和��。 (由 Tal Einat 和 Saimadhav Heblikar 在 bpo-17535 中贡献。)

现在会使用 OS 本机编�格�在 Python 字符串和 Tcl 对象间进行转�。 这�许在 IDLE 中处� emoji 和其他� BMP 字符。 这些字符将�被显示或是从剪贴��制和粘贴。 字符串从 Tcl 到 Python 的�回转�现在�会��生失败。 (过去八年有许多人都为此付出过努力,问题最终由 Serhiy Storchaka 在 bpo-13153 中解决。)

在 3.8.1 中新增:

添加切�光标闪��止的选项。 (由 Zackery Spytz 在 bpo-4603 中贡献。)

Esc 键现在会关闭 IDLE 补全�示窗�。 (由 Johnny Najera 在 bpo-38944 中贡献。)

上述修改已被��移�到 3.7 维护�行版中。

添加关键字到模��称补全列表。 (由 Terry J. Reedy 在 bpo-37765 中贡献。)

inspect¶

inspect.getdoc() 函数现在�以找到 __slots__ 的文档字符串,如果该属性是一个元素值为文档字符串的 dict 的�。 这�供了类似于目�已有的 property(), classmethod() 和 staticmethod() 等函数的文档选项:

class AudioClip:
    __slots__ = {'bit_rate': 'expressed in kilohertz to one decimal place',
                 'duration': 'in seconds, rounded up to an integer'}
    def __init__(self, bit_rate, duration):
        self.bit_rate = round(bit_rate / 1000.0, 1)
        self.duration = ceil(duration)

(由 Raymond Hettinger 在 bpo-36326 中贡献。)

io¶

在开�模� (-X env) 和 调试编译版 中,io.IOBase 终结器现在会在 close() 方法失败时将异常写入日志。 �生的异常在�布编译版中会被�默地忽略。 (由 Victor Stinner 在 bpo-18748 中贡献。)

itertools¶

itertools.accumulate() 函数增加了�选的 initial 关键字�数用�指定一个�始值:

>>> from itertools import accumulate
>>> list(accumulate([10, 5, 30, 15], initial=1000))
[1000, 1010, 1015, 1045, 1060]

(由 Lisa Roach 在 bpo-34659 中贡献。)

json.tool¶

添加选项 --json-lines 用于将�个输入行解�为�独的 JSON 对象。 (由 Weipeng Hong 在 bpo-31553 中贡献。)

logging¶

为 logging.basicConfig() 添加了 force 关键字�数,当设为真值时,关�到根日志记录器的任何现有处�程�都将在执行由其他�数所指定的�置之�被移除并关闭。

这解决了一个长期存在的问题。 当一个日志处�器或 basicConfig() 被调用时,对 basicConfig() 的�续调用会被�默地忽略。 这导致使用交互�示符或 Jupyter 笔记本更新�试验或讲解��日志�置选项�得相当困难。

(由 Raymond Hettinger �议,由 Donghee Na 实现,并由 Vinay Sajip 审核�在 bpo-33897 中贡献。)

math¶

添加了新的函数 math.dist() 用于计算两点之间的欧几里得�离。 (由 Raymond Hettinger 在 bpo-33089 中贡献。)

扩展了 math.hypot() 函数以便处�更多的维度。 之�它仅支� 2-D 的情况。 (由 Raymond Hettinger 在 bpo-33089 中贡献。)

添加了新的函数 math.prod() 作为的 sum() �类,该函数返回 'start' 值 (默认值: 1) 乘以一个数字�迭代对象的积:

>>> prior = 0.8
>>> likelihoods = [0.625, 0.84, 0.30]
>>> math.prod(likelihoods, start=prior)
0.126

(由 Pablo Galindo 在 bpo-35606 中贡献。)

添加了两个新的组�函数 math.perm() 和 math.comb():

>>> math.perm(10, 3)    # Permutations of 10 things taken 3 at a time
720
>>> math.comb(10, 3)    # Combinations of 10 things taken 3 at a time
120

(由 Yash Aggarwal, Keller Fuchs, Serhiy Storchaka 和 Raymond Hettinger 在 bpo-37128, bpo-37178 和 bpo-35431 中贡献。)

添加了一个新函数 math.isqrt() 用于计算精确整数平方根而无需转�为浮点数。 该新函数支�任�大整数。 它的执行速度比 floor(sqrt(n)) 快但是比 math.sqrt() 慢:

>>> r = 650320427
>>> s = r ** 2
>>> isqrt(s - 1)         # correct
650320426
>>> floor(sqrt(s - 1))   # incorrect
650320427

(由 Mark Dickinson 在 bpo-36887 中贡献。)

函数 math.factorial() ��接��整数类�数。 (由 Pablo Galindo 在 bpo-33083 中贡献。)

mmap¶

mmap.mmap 类现在具有一个 madvise() 方法用于访问 madvise() 系统调用。 (由 Zackery Spytz 在 bpo-32941 中贡献。)

multiprocessing¶

添加了新的 multiprocessing.shared_memory 模�。 (由 Davin Potts 在 bpo-35813 中贡献。)

在macOS上,现在默认使用的�动方�是*spawn*�动方�。 (由 Victor Stinner 在 bpo-33725 中贡献。)

os¶

在 Windows 上添加了新函数 add_dll_directory() 用于在导入扩展模�或使用 ctypes 加载 DLL 时为本机�赖�供�外�索路径 。 (由 Steve Dower 在 bpo-36085 中贡献。)

添加了新的 os.memfd_create() 函数用于包装 memfd_create() 系统调用。 (由 Zackery Spytz 和 Christian Heimes 在 bpo-26836 中贡献。)

在 Windows 上,大部分用于处��解�点,(包括符�链接和目录连接)的手动逻辑已被委托给�作系统。 特别地,os.stat() 现在将会�历�作系统所支�的任何内容,而 os.lstat() 将�打开被标识为“�称代��的�解�点,而其�由 os.stat() 打开其他的�解�点。 在所有情况下,stat_result.st_mode 将�为符�链接而�其他�类的�解�点设置 S_IFLNK。 �标识其他�类的�解�点,请检查新的 stat_result.st_reparse_tag 属性。

在 Windows 上,os.readlink() 现在能够读�目录连接。 请注� islink() 会对目录连接返回 False,因此首先检查 islink 的代�将连续把连接视为目录,而会处� os.readlink() 所引�错误的代�现在会把连接视为链接。

(由 Steve Dower 在 bpo-37834 中贡献。)

os.path¶

返回布尔值结果的 os.path 函数例如 exists(), lexists(), isdir(), isfile(), islink(), 以� ismount() 现在对于包�在 OS 层级无法表示的字符或字节的路径将会返回 False 而�是引� ValueError 或其�类 UnicodeEncodeError 和 UnicodeDecodeError。 (由 Serhiy Storchaka 在 bpo-33721 中贡献。)

expanduser() 在 Windows 上现在改用 USERPROFILE 环境��而��使用 HOME,�者通常�会为一般用户账户设置。 (由 Anthony Sottile 在 bpo-36264 中贡献。)

isdir() 在 Windows 上将��为�存在的目录的链接返回 True。

realpath() 在 Windows 上现在会识别�解�点,包括符�链接和目录连接。

(由 Steve Dower 在 bpo-37834 中贡献。)

pathlib¶

返回布尔值结果的 pathlib.Path 方法例如 exists(), is_dir(), is_file(), is_mount(), is_symlink(), is_block_device(), is_char_device(), is_fifo(), is_socket() 现在对于包�在 OS 层级无法表示的字符或字节的路径将会返回 False 而�是引� ValueError 或其�类 UnicodeEncodeError。 (由 Serhiy Storchaka 在 bpo-33721 中贡献。)

添加了 pathlib.Path.link_to(),它�以创建指�一个路径的硬链接。 (由 Joannah Nanjekye 在 bpo-26978 中贡献) 请注� link_to 在 3.10 中被弃用并在 3.12 中被移除并改用在 3.10 中添加的 hardlink_to 方法,它与现有 symlink_to 的语法相匹�。

pickle¶

pickle 扩展�类化针对 C 优化的 Pickler 现在�通过定义特殊的 reducer_override() 方法��载函数和类的�存逻辑。 (由 Pierre Glaser 和 Olivier Grisel 在 bpo-35900 中贡献。)

plistlib¶

添加了新的 plistlib.UID 并�动了对读�和写入�过 NSKeyedArchiver 编�的二进制 plists 的支�。 (由 Jon Janzen 在 bpo-26707 中贡献。)

pprint¶

pprint 模�为一些函数添加了 sort_dicts 形�。 默认情况下,这些函数会继续在渲染或打�之�对字典进行排�。 但是,如果 sort_dicts 设为�值,则字典将��键�入时的顺�。 这在调试期间与 JSON 输入进行比较时会很有用。

除此之外,还增加了一个方便的新函数 pprint.pp(),它类似于 pprint.pprint() 但它的 sort_dicts 默认为 False:

>>> from pprint import pprint, pp
>>> d = dict(source='input.txt', operation='filter', destination='output.txt')
>>> pp(d, width=40)                  # Original order
{'source': 'input.txt',
 'operation': 'filter',
 'destination': 'output.txt'}
>>> pprint(d, width=40)              # Keys sorted alphabetically
{'destination': 'output.txt',
 'operation': 'filter',
 'source': 'input.txt'}

(由 Rémi Lapeyre 在 bpo-30670 中贡献。)

py_compile¶

py_compile.compile() 现在支��默模�。 (由 Joannah Nanjekye 在 bpo-22640 中贡献。)

shlex¶

新增了 shlex.join() 函数作为 shlex.split() 的逆�作。 (由 Bo Bayles 在 bpo-32102 中贡献。)

shutil¶

shutil.copytree() 现在接�新的 dirs_exist_ok 关键字�数。 (由 Josh Bronson 在 bpo-20849 中贡献。)

shutil.make_archive() 现在对新的归档默认使用 modern pax (POSIX.1-2001) 格�以���移�性和标准一致性,此特性继承自对 tarfile 模�的相应更改。 (由 C.A.M. Gerlach 在 bpo-30661 中贡献。)

shutil.rmtree() 在 Windows 上现在会移除目录连接而�会递归地先移除其中的内容。 (由 Steve Dower 在 bpo-37834 中贡献。)

socket¶

添加了便�的 create_server() 和 has_dualstack_ipv6() 函数以自动化在创建�务器套接字时通常情况下所必须的任务,包括在�一套接字中�时接� IPv4 和 IPv6 连接。 (由 Giampaolo Rodolà 在 bpo-17561 中贡献。)

socket.if_nameindex(), socket.if_nametoindex() 和 socket.if_indextoname() 函数已�在 Windows 上实现。 (由 Zackery Spytz 在 bpo-37007 中贡献。)

ssl¶

增加了 post_handshake_auth 和 verify_client_post_handshake() 分别�用和�始化 TLS 1.3 �手�验�。 (由 Christian Heimes 在 bpo-34670 中贡献。)

statistics¶

添加了 statistics.fmean() 作为 statistics.mean() 的更快速的浮点数版版本。 (由 Raymond Hettinger 和 Steven D'Aprano 在 bpo-35904 中贡献。)

添加了 statistics.geometric_mean() (由 Raymond Hettinger 在 bpo-27181 中贡献。)

添加了 statistics.multimode() 用于返回最常�值的列表。 (由 Raymond Hettinger 在 bpo-35892 中贡献。)

添加了 statistics.quantiles() 用于将数�或分布划分为多个等概率区间(例如四分���分�或百分�)。 (由 Raymond Hettinger 在 bpo-36546 中贡献。)

添加了 statistics.NormalDist 用于创建和�纵�机��的正�分布。 (由 Raymond Hettinger 在 bpo-36018 中贡献。)

>>> temperature_feb = NormalDist.from_samples([4, 12, -3, 2, 7, 14])
>>> temperature_feb.mean
6.0
>>> temperature_feb.stdev
6.356099432828281

>>> temperature_feb.cdf(3)            # Chance of being under 3 degrees
0.3184678262814532
>>> # Relative chance of being 7 degrees versus 10 degrees
>>> temperature_feb.pdf(7) / temperature_feb.pdf(10)
1.2039930378537762

>>> el_niño = NormalDist(4, 2.5)
>>> temperature_feb += el_niño        # Add in a climate effect
>>> temperature_feb
NormalDist(mu=10.0, sigma=6.830080526611674)

>>> temperature_feb * (9/5) + 32      # Convert to Fahrenheit
NormalDist(mu=50.0, sigma=12.294144947901014)
>>> temperature_feb.samples(3)        # Generate random samples
[7.672102882379219, 12.000027119750287, 4.647488369766392]

sys¶

添加了新的 sys.unraisablehook() 函数,�被�载以便控制如何处�“��引�的异常�。 它会在�生了一个异常但 Python 没有办法处�时被调用。 例如,当一个�构器在垃圾回收时 (gc.collect()) 所引�的异常。 (由 Victor Stinner 在 bpo-36829 中贡献。)

tarfile¶

tarfile 模�现在对新的归档默认使用 modern pax (POSIX.1-2001) 格�而��是之�的 GNU 专属格�。 这通过标准化和�扩展格�的统一编� (UTF-8) ��了跨平��移�性,还�供了其他一些益处。 (由 C.A.M. Gerlach 在 bpo-36268 中贡献。)

threading¶

添加了新的 threading.excepthook() 函数用�处�未�获的 threading.Thread.run() 异常。 它�被�载以便控制如何处�未�获的 threading.Thread.run() 异常。 (由 Victor Stinner 在 bpo-1230540 中贡献。)

添加了新的 threading.get_native_id() 函数以� threading.Thread 类的 native_id 属性。 它们会返回内核所分�给当�线程的原生整数线程 ID。 此特性仅在特定平�上�用,�� get_native_id 了解详情。 (由 Jake Tesler 在 bpo-36084 中贡献。)

tokenize¶

当�供�带末尾新行的输入时,tokenize 模�现在会��地添加 NEWLINE 形符。 此行为现在已与 C �法分�器的内部行为相匹�。 (由 Ammar Askar 在 bpo-33899 中贡献。)

tkinter¶

在 tkinter.Spinbox 中添加了方法 selection_from(), selection_present(), selection_range() 和 selection_to()。 (由 Juliette Monsel 在 bpo-34829 中贡献。)

在 tkinter.Canvas 类中添加了方法 moveto()。 (由 Juliette Monsel 在 bpo-23831 中贡献。)

tkinter.PhotoImage 类现在具有 transparency_get() 和 transparency_set() 方法。 (由 Zackery Spytz 在 bpo-25451 中贡献。)

time¶

为 macOS 10.12 添加了新的时钟 CLOCK_UPTIME_RAW。 (由 Joannah Nanjekye 在 bpo-35702 中贡献。)

typing¶

typing 模�加入了一些新特性:

  • 一个带有键专属类型的字典类型。 å�‚è§� PEP 589 å’Œ typing.TypedDict。 TypedDict å�ªä½¿ç”¨å­—符串作为键。 默认情况下æ¯�个键都è¦�求æ��供。 指定 "total=False" 以å…�许键作为å�¯é€‰é¡¹:

    class Location(TypedDict, total=False):
        lat_long: tuple
        grid_square: str
        xy_coordinate: tuple
    
  • Literal 类型。 å�‚è§� PEP 586 å’Œ typing.Literal。 Literal 类型指明一个形å�‚或返回值被é™�定为一个或多个特定的字é�¢å€¼:

    def get_status(port: int) -> Literal['connected', 'disconnected']:
        ...
    
  • "Final" å�˜é‡�ã€�函数ã€�方法和类。 å�‚è§� PEP 591, typing.Final å’Œ typing.final()。 final é™�定符会指示é�™æ€�类型检查器é™�制进行å­�类化ã€�é‡�载或é‡�新赋值:

    pi: Final[float] = 3.1415926536
    
  • å��议定义。 å�‚è§� PEP 544, typing.Protocol å’Œ typing.runtime_checkable()。 简å�•çš„ ABC 例如 typing.SupportsInt 现在是 Protocol çš„å­�类。

  • æ–°çš„å��议类 typing.SupportsIndex。

  • 新的函数 typing.get_origin() å’Œ typing.get_args()。

unicodedata¶

unicodedata 模�现在已�级为使用 Unicode 12.1.0 �布版。

新的函数 is_normalized() �被用�验�字符串是�为特定正规形�,通常会比实际进行字符串正规化�快得多。 (由 Max Belanger, David Euresti 和 Greg Price 在 bpo-32285 和 bpo-37966 中贡献。)

unittest¶

添加了 AsyncMock 以支�异步版本的 Mock。 �时也添加了相应的断言函数用于测试。 (由 Lisa Roach 在 bpo-26467 中贡献。)

unittest 添加了 addModuleCleanup() 和 addClassCleanup() 以支�对 setUpModule() 和 setUpClass() 进行清�。 (由 Lisa Roach 在 bpo-24412 中贡献。)

一些模拟断言函数现在也会在失败时打�一个实际调用列表。 (由 Petter Strandmark 在 bpo-35047 中贡献。)

unittest 模�已支�通过 unittest.IsolatedAsyncioTestCase �使用�程作为测试用例。 (由 Andrew Svetlov 在 bpo-32972 中贡献。)

示例:

import unittest


class TestRequest(unittest.IsolatedAsyncioTestCase):

    async def asyncSetUp(self):
        self.connection = await AsyncConnection()

    async def test_get(self):
        response = await self.connection.get("https://example.com")
        self.assertEqual(response.status_code, 200)

    async def asyncTearDown(self):
        await self.connection.close()


if __name__ == "__main__":
    unittest.main()

venv¶

现在 venv 在所有平�上都会包� Activate.ps1 脚本用于在 PowerShell Core 6.1 下激活虚拟环境。 (由 Brett Cannon 在 bpo-32718 中贡献。)

weakref¶

由 weakref.proxy() 返回的代�对象现在除其他算术�算符外也支�矩阵乘法�算符 @ 和 @=。 (由 Mark Dickinson 在 bpo-36669 中贡献。)

xml¶

作为对 DTD 和外部实体检索的缓解,在默认情况下 xml.dom.minidom 和 xml.sax 模���处�外部实体。 (由 Christian Heimes 在 bpo-17239 中贡献。)

xml.etree.ElementTree 模�中的 .find*() 方法支�通�符�索例如 {*}tag,此�索会忽略命�空间以�返回给定命�空间中所有标签的 {namespace}*。 (由 Stefan Behnel 在 bpo-28238 中贡献。)

xml.etree.ElementTree 模��供了实现 C14N 2.0 的新函数 –xml.etree.ElementTree.canonicalize()。 (由 Stefan Behnel 在 bpo-13611 中贡献。)

xml.etree.ElementTree.XMLParser 的目标对象�通过新的回调方法 start_ns() 和 end_ns() �接�命�空间声明事件。 此外,xml.etree.ElementTree.TreeBuilder 目标�被�置为处�有关注释和处�指令事件以将它们包�在所生�的树当中。 (由 Stefan Behnel 在 bpo-36676 和 bpo-36673 中贡献。)

xmlrpc¶

xmlrpc.client.ServerProxy 现在支��选的 headers 关键字�数作为���次请求��的 HTTP 标头�列。 此特�的作用之一是使得从默认的基础认��级到更快速的会�认��为�能。 (由 Cédric Krier 在 bpo-35153 中贡献。)

性能优化¶

  • subprocess 模å�—现在能在æŸ�些情况下使用 os.posix_spawn() 函数以获得更好的性能。 ç›®å‰�,它的使用仅é™� macOS å’Œ Linux(使用 glibc 2.24 或更新版本),并è¦�求满足以下æ�¡ä»¶ï¼š

    • close_fds 为å�‡å€¼ï¼›

    • preexec_fn, pass_fds, cwd å’Œ start_new_session å½¢å�‚未设置;

    • executable 路径包å�«ä¸€ä¸ªç›®å½•。

    (由 Joannah Nanjekye 和 Victor Stinner 在 bpo-35537 中贡献。)

  • shutil.copyfile(), shutil.copy(), shutil.copy2(), shutil.copytree() å’Œ shutil.move() 在 Linux å’Œ macOS 上会使用平å�°ä¸“属的 "fast-copy" 系统调用以æ��高效率。 "fast-copy" æ„�味ç�€æ‹·è´�æ“�作å�‘生于内核中,从而é�¿å…�在进行 "outfd.write(infd.read())" ç­‰æ“�作时使用 Python 中的用户空间缓冲区。 在 Windows 上 shutil.copyfile() 会使用更大的默认缓冲区(1 MiB 而ä¸�是 16 KiB)并且使用基于 memoryview() çš„ shutil.copyfileobj() 版本。 在å�Œä¸€åˆ†åŒºå†…æ‹·è´�一个 512 MiB 文件的速度æ��å�‡åœ¨ Linux 上约为 +26%,在 macOS 上为 +50%,在 Windows 上为 +40%。 此外还将消耗更少的 CPU 周期。 å�‚è§� ä¾�赖于具体平å�°çš„高效拷è´�æ“�作 一节。 (由 Giampaolo Rodolà 在 bpo-33671 中贡献。)

  • shutil.copytree() 会根æ�®å…¶æ‰€ç”¨ç¼“存的 os.stat() 值使用 os.scandir() 函数å�Šæ‰€æœ‰æ‹·è´�函数。 æ‹·è´�一个包å�« 8000 文件的目录的速度æ��å�‡åœ¨ Linux 上约为 +9%,在 Windows 上为 +20%,对于 Windows SMB 共享目录则为 +30%。 此外 os.stat() 系统调用的次数也å‡�少了 38%,使得 shutil.copytree() 在网络文件系统上会特别快速。 (由Giampaolo Rodolà 在 bpo-33695 中贡献。)

  • pickle 模å�—使用的默认å��议现在为 Protocol 4,最早在 Python 3.4 中被引入。 它æ��供了比自 Python 3.0 èµ·å�¯ç”¨çš„ Protocol 3 更好的性能和更å°�的数æ�®å°ºå¯¸ã€‚

  • 从 PyGC_Head 移除了一个 Py_ssize_t æˆ�员。 所有跟踪 GC 的对象(例如 tuple, list, dict)大å°�å‡�少了 4 或 8 字节。 (由 Inada Naoki 在 bpo-33597 中贡献。)

  • uuid.UUID 现在会使用 __slots__ 以å‡�少内存足迹。 (由 Wouter Bolsterlee å’Œ Tal Einat 在 bpo-30977 中贡献。)

  • operator.itemgetter() 的性能æ��å�‡äº† 33%。 优化了å�‚数处ç�†ï¼Œå¹¶ä¸ºå¸¸è§�的在元组中å�•个é�žè´Ÿæ•´æ•°ç´¢å¼•的情况新增了一æ�¡å¿«é€Ÿè·¯å¾„(这是标准库中的典型用例)。 (由 Raymond Hettinger 在 bpo-35664 中贡献。

  • 加快了在 collections.namedtuple() 中的字段查找。 它们现在的速度快了两å€�以上,æˆ�为 Python 中最快的实例å�˜é‡�查找形å¼�。 (由 Raymond Hettinger, Pablo Galindo å’Œ Joe Jevnik, Serhiy Storchaka 在 bpo-32492 中贡献。)

  • 如果输入的å�¯è¿­ä»£å¯¹è±¡çš„长度已知 (å�³è¾“入对象实现了 __len__),list 构造器ä¸�会过度分é…�内部项缓冲区。 这使得所创建的列表资æº�å� ç”¨å¹³å�‡å‡�少了 12%。 (由 Raymond Hettinger å’Œ Pablo Galindo 在 bpo-33234 中贡献。)

  • ç±»å�˜é‡�写入速度加å€�。 当一个é�žå†—余属性被更新时,之å‰�存在一个更新 slots çš„é�žå¿…è¦�调用。 (由 Stefan Behnel, Pablo Galindo Salgado, Raymond Hettinger, Neil Schemenauer, å’Œ Serhiy Storchaka 在 bpo-36012 中贡献。)

  • å‡�少了传递给许多内置函数和方法的å�‚数转æ�¢çš„开销。 这使得æŸ�些简å�•内置函数和方法的速度æ��å�‡äº† 20--50%。 (由 Serhiy Storchaka 在 bpo-23867, bpo-35582 å’Œ bpo-36127 中贡献。)

  • LOAD_GLOBAL 指令现在会使用新的 "per opcode cache" 机制。 它的速度现在æ��å�‡äº†å¤§çº¦ 40%。 (由 Yury Selivanov å’Œ Inada Naoki 在 bpo-26219 中贡献。)

构建和 C API 的改�¶

  • 默认的 sys.abiflags æˆ�为一个空字符串:pymalloc çš„ m æ——æ ‡ä¸�å†�有æ„�义(无论是å�¦å�¯ç”¨ pymalloc 构建都是兼容 ABI 的)因此已被移除。 (由 Victor Stinner 在 bpo-36707 中贡献。)

    改�的例�:

    • å�ªä¼šå®‰è£… python3.8 程åº�,ä¸�å†�有 python3.8m 程åº�。

    • å�ªä¼šå®‰è£… python3.8-config 脚本,ä¸�å†�有 python3.8m-config 脚本。

    • m 旗标已ç»�从动æ€�库文件å��å�Žç¼€ä¸­ç§»é™¤ï¼šåŒ…括标准库中的扩展模å�—以å�Šç¬¬ä¸‰æ–¹åŒ…所产生和安装的模å�—例如从 PyPI 下载的模å�—。 以 Linux 为例,Python 3.7 çš„å�Žç¼€ .cpython-37m-x86_64-linux-gnu.so 在 Python 3.8 中改为 .cpython-38-x86_64-linux-gnu.so。

  • é‡�新组织了所有头文件以更好地区分ä¸�å�Œç§�类的 API:

    • Include/*.h 应为å�¯ç§»æ¤�的公有稳定版 C API。

    • Include/cpython/*.h 应为 CPython 专属的ä¸�稳定版 C API;公有 API,部分ç§�有 API 附加 _Py or _PY å‰�缀。

    • Include/internal/*.h 应为 CPython 特别专属的ç§�有内部 C API。 æ­¤ API ä¸�具备å�‘下兼容ä¿�è¯�并且ä¸�应在 CPython 以外被使用。 它们的公开仅适用于特别é™�定的需求例如调试器和性能分æž�等必须直接访问 CPython 内部数æ�®è€Œä¸�通过调用函数的应用。 æ­¤ API 现在是通过 make install 安装的。

    (由 Victor Stinner 在 bpo-35134 和 bpo-35081 中贡献,相关工作由 Eric Snow 在 Python 3.7 中�起。)

  • æŸ�些å®�已被转æ�¢ä¸ºé�™æ€�内è�”函数:形å�‚类型和返回类型定义良好,它们ä¸�å†�会有与å®�相关的问题,å�˜é‡�具有局部作用域。 例如:

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

  • PyByteArray_Init() å’Œ PyByteArray_Fini() 函数已被移除。 它们自 Python 2.7.4 å’Œ Python 3.2.0 起就没有任何用处,被排除在å�—é™� API (稳定 ABI) 之外,并且未被写入文档。 (由 Victor Stinner 在 bpo-35713 中贡献。)

  • PyExceptionClass_Name() 的结果类型现在是 const char * 而é�ž char *。 (由 Serhiy Storchaka 在 bpo-33818 中贡献。)

  • Modules/Setup.dist 与 Modules/Setup 两者的共存已被移除。 之å‰�在更新 CPython æº�ç �树时,开å�‘者必须手动拷è´� Modules/Setup.dist (在æº�ç �树内) 到 Modules/Setup (在构建树内) 以å��映上游的任何改å�˜ã€‚ 旧特性对打包者æ�¥è¯´æœ‰ä¸€ç‚¹ç›Šå¤„,但代价是对追踪 CPython å¼€å�‘进程的开å�‘者造æˆ�ç»�常性的麻烦,因为忘记拷è´�该文件å�¯èƒ½å¯¼è‡´æž„建失败。

    现在构建系统总是会从��树内的 Modules/Setup 读�数�。 建议希望定制该文件的开�者在 CPython 的一个 git 分�或补�文件中维护他们的更改,就如他们对��树�任何其他改�时一样。

    (由 Antoine Pitrou 在 bpo-32430 中贡献。)

  • å°† Python 数字转æ�¢ä¸º C 整型的函数例如 PyLong_AsLong() 以å�Šå¸¦æœ‰ 'i' 之类整型转æ�¢æ ¼å¼�å�•元的å�‚æ•°è§£æž�函数例如 PyArg_ParseTuple() 现在如果å�¯èƒ½å°†ä¼šä½¿ç”¨ __index__() 特殊方法而ä¸�是 __int__()。 对于带有 __int__() 方法但没有 __index__() 方法的对象 (例如 Decimal å’Œ Fraction) 将会å�‘出弃用警告。 对于实现了 __index__() 的对象 PyNumber_Check() 现在将返回 1。 PyNumber_Long(), PyNumber_Float() å’Œ PyFloat_AsDouble() 现在如果å�¯èƒ½ä¹Ÿå°†ä¼šä½¿ç”¨ __index__() 方法。 (由 Serhiy Storchaka 在 bpo-36048 å’Œ bpo-20092 中贡献。)

  • 堆分é…�类型对象现在将增加它们在 PyObject_Init() (å�Šå…¶å¯¹åº”çš„å®� PyObject_INIT) 中的引用计数而ä¸�是在 PyType_GenericAlloc() 中。 修改实例分é…�或中止分é…�的类型å�¯èƒ½éœ€è¦�进行调整。 (由 Elizondo 在 bpo-35810 中贡献。)

  • 新增函数 PyCode_NewWithPosOnlyArgs() å…�许创建代ç �对象如 PyCode_New(),但带有一个é¢�外的 posonlyargcount å½¢å�‚以指明仅é™�ä½�ç½®å�‚数的数é‡�。 (由 Pablo Galindo 在 bpo-37221 中贡献。)

  • Py_SetPath() 现在会将 sys.executable 设置为程åº�完整路径 (Py_GetProgramFullPath()) 而ä¸�是程åº�å��ç§° (Py_GetProgramName())。 (由 Victor Stinner 在 bpo-38234 中贡献。)

弃用¶

  • distutils çš„ bdist_wininst 命令现在已弃用,请改用 bdist_wheel (wheel 包)。 (由 Victor Stinner 在 bpo-37481 中贡献。)

  • ElementTree 模å�—中的已弃用方法 getchildren() å’Œ getiterator() 现在会引å�‘ DeprecationWarning 而ä¸�是 PendingDeprecationWarning。 它们将在 Python 3.9 中被移除。 (由 Serhiy Storchaka 在 bpo-29209 中贡献。)

  • å°†ä¸�是 concurrent.futures.ThreadPoolExecutor 的实例的对象传给 loop.set_default_executor() 已被弃用,并将在 Python 3.9 中被ç¦�止。 (由 Elvis Pranskevichus 在 bpo-34075 中贡献。)

  • xml.dom.pulldom.DOMEventStream, wsgiref.util.FileWrapper å’Œ fileinput.FileInput çš„ __getitem__() 方法已被弃用。

    这些方法的实现会忽略它们的 index 形�,并改为返回下一�目。 (由 Berker Peksag 在 bpo-9372 中贡献。)

  • typing.NamedTuple 类已弃用了 _field_types 属性而改用具有å�Œæ ·ä¿¡æ�¯çš„ __annotations__ 属性。 (由 Raymond Hettinger 在 bpo-36320 中贡献。)

  • ast ç±» Num, Str, Bytes, NameConstant å’Œ Ellipsis 被视为已弃用并将在未æ�¥çš„ Python 版本中被移除。 应当改用 Constant。 (由 Serhiy Storchaka 在 bpo-32892 中贡献。)

  • ast.NodeVisitor 的方法 visit_Num(), visit_Str(), visit_Bytes(), visit_NameConstant() å’Œ visit_Ellipsis() 现在已被弃用,并且在未æ�¥çš„ Python 版本中将ä¸�å†�被调用。 添加 visit_Constant() 方法æ�¥å¤„ç�†æ‰€æœ‰å¸¸é‡�节点。 (由 Serhiy Storchaka 在 bpo-36917 中贡献。)

  • asyncio.coroutine() decorator 已弃用并将在 3.10 版中被移除。 原有的 @asyncio.coroutine 请改用 async def æ�¥æ›¿ä»£ã€‚ (由 Andrew Svetlov 在 bpo-36921 中贡献。)

  • 在 asyncio 中,loop å�‚数的显å¼�传递已被弃用并且到 3.10 版时将会在以下函数中被移除: asyncio.sleep(), asyncio.gather(), asyncio.shield(), asyncio.wait_for(), asyncio.wait(), asyncio.as_completed(), asyncio.Task, asyncio.Lock, asyncio.Event, asyncio.Condition, asyncio.Semaphore, asyncio.BoundedSemaphore, asyncio.Queue, asyncio.create_subprocess_exec() 以å�Š asyncio.create_subprocess_shell()。

  • å°†å��程对象显å¼�传递给 asyncio.wait() çš„å�šæ³•å·²è¢«å¼ƒç”¨å¹¶ä¸”å°†åœ¨ 3.11 版中被移除。 (由 Yury Selivanov 在 bpo-34790 中贡献。)

  • gettext 模å�—中的下列函数和方法已被弃用: lgettext(), ldgettext(), lngettext() å’Œ ldngettext()。 它们返回已编ç �的字节串,如果转æ�¢å�Žçš„字符串存在编ç �问题你将å�¯èƒ½é�­é�‡é¢„期之外的异常。 更好的å�šæ³•æ˜¯ä½¿ç”¨ Python 3 中返回 Unicode 字符串的æ“�作作为替代。 å‰�é�¢çš„函数都早已ä¸�宜使用。

    函数 bind_textdomain_codeset(),方法 output_charset() 和 set_output_charset(),以�函数 translation() 和 install() 的 codeset 形�也已被弃用,因为它们仅适用于 l*gettext() 函数。 (由 Serhiy Storchaka 在 bpo-33710 中贡献。)

  • threading.Thread çš„ isAlive() 方法已被弃用。 (由 Donghee Na 在 bpo-35283 中贡献。)

  • 许多接å�—æ•´æ•°å�‚数的内置和扩展模å�—的函数现在将对传入 Decimal, Fraction 以å�Šä»»ä½•å…¶ä»–å�¯è¢«è½¬æ�¢ä¸ºæ•´æ•°ä½†ä¼šä¸¢å¤±ç²¾åº¦ï¼ˆå�³å…·æœ‰ __int__() 方法但没有 __index__() 方法)的对象å�‘出弃用警告。 在未æ�¥çš„版本中则将报错。 (由 Serhiy Storchaka 在 bpo-36048 中贡献。)

  • 以下å�‚数作为关键字å�‚数传递的方å¼�已被弃用:

    在未�版本的 Python 中,它们将�为 仅��置�数。 (由 Serhiy Storchaka 在 bpo-36492 中贡献。)

API 与特性的移除¶

下列特性与 API 已从 Python 3.8 中移除:

  • 自 Python 3.3 起,从 collections 导入 ABC çš„å�šæ³•å·²å¼ƒç”¨ï¼Œè€Œåº”å½“ä»Ž collections.abc 执行导入。 从 collections 导入的æ“�作在 3.8 中已标记为被移除,但将推迟到 3.9 中实施。 (å�‚è§� bpo-36952。)

  • macpath 模å�—,在 Python 3.7 中弃用,现已被移除。 (由 Victor Stinner 在 bpo-35471 中贡献。)

  • 函数 platform.popen() 已被移除,它自 Python 3.3 起就已被弃用:请改用 os.popen()。 (由 Victor Stinner 在 bpo-35345 中贡献。)

  • 函数 time.clock() 已被移除,它自 Python 3.3 起就已被弃用:请根æ�®å…·ä½“需求改用 time.perf_counter() 或 time.process_time() 以获得具有良好定义的行为。 (由 Matthias Bussonnier 在 bpo-36895 中贡献。)

  • pyvenv 脚本已被移除,推è��改用 python3.8 -m venv æ�¥å¸®åŠ©æ¶ˆé™¤å®¹æ˜“æ··æ·† pyvenv 脚本所关è�”çš„ Python 解释器这一问题。 (由 Brett Cannon 在 bpo-25427 中贡献。)

  • parse_qs, parse_qsl å’Œ escape 已从 cgi 模å�—中被移除。 这些函数自 Python 3.2 或更早就已被弃用。 它们应改为从 urllib.parse å’Œ html 模å�—导入。

  • filemode 函数已从 tarfile 模å�—中被移除。 该函数未被写入文档,自 Python 3.3 起就已弃用。

  • XMLParser 构造器ä¸�å†�接å�— html å�‚数。 它从æ�¥æ²¡æœ‰ä»»ä½•作用并在 Python 3.4 中已被弃用。 所有其他形å�‚现在都是 ä»…é™�关键字å�‚数。 (由 Serhiy Storchaka 在 bpo-29209 中贡献。)

  • XMLParser çš„ doctype() 方法已被移除。 (由 Serhiy Storchaka 在 bpo-29209 中贡献。)

  • "unicode_internal" ç¼–è§£ç �器已被移除。 (由 Inada Naoki 在 bpo-36297 中贡献。)

  • sqlite3 模å�—çš„ Cache å’Œ Statement 对象已ä¸�å†�公开给用户。 (由 Aviv Palivoda 在 bpo-30262 中贡献。)

  • fileinput.input() å’Œ fileinput.FileInput() 中自 Python 3.6 起就已被忽略并弃用的 bufsize 关键字å�‚数已被移除。 ç”± Matthias Bussonnier 在 bpo-36952 中贡献。)

  • 在 Python 3.7 中弃用的函数 sys.set_coroutine_wrapper() å’Œ sys.get_coroutine_wrapper() 已被移除。 (由 Matthias Bussonnier 在 bpo-36933 中贡献。)

移�到 Python 3.8¶

本节列出了先��述的更改以��能需�更改代�的其他错误修正.

Python 行为的改�¶

  • yield 表达å¼�(包括 yield å’Œ yield from å­�å�¥ï¼‰çŽ°åœ¨ä¸�å…�许在推导å¼�和生æˆ�器表达å¼�中使用(但最左边的 for å­�å�¥ä¸­çš„å�¯è¿­ä»£å¯¹è±¡è¡¨è¾¾å¼�除外)。 (由 Serhiy Storchaka 在 bpo-10544 中贡献。)

  • 当标识å�·æ£€æµ‹ (is å’Œ is not) 与特定类型的字é�¢å€¼ (例如字符串和数字) 一å�Œä½¿ç”¨æ—¶ç¼–译器现在会产生 SyntaxWarning。 这在 CPython 中通常是å�¯è¡Œçš„,但并ä¸�被语言定义所ä¿�è¯�。 该警告会建议用户改用相等性检测 (== and !=)。 (由 Serhiy Storchaka 在 bpo-34850 中贡献。)

  • CPython 解释器在æŸ�些情况下å�¯ä»¥å¿½ç•¥å¼‚常。 在 Python 3.8 中这ç§�情况会更少å�‘生。 特别地,从类型字典获å�–属性时引å�‘的异常ä¸�会å†�被忽略。 (由 Serhiy Storchaka 在 bpo-35459 中贡献。)

  • 从内置类型 bool, int, float, complex 和标准库的一些类中移除了 __str__ 实现。 它们现在会从 object 继承 __str__()。 作为结果,在这些类的å­�类中定义 __repr__() 方法将会影å“�它们的字符串表示。 (由 Serhiy Storchaka 在 bpo-36793 中贡献。)

  • 在 AIX 上,sys.platform å°†ä¸�å†�包å�«ä¸»è¦�版本å�·ã€‚ 它将总是 'aix',而ä¸�是 'aix3' .. 'aix7'。 由于较旧的 Python 版本会包å�«ç‰ˆæœ¬å�·ï¼Œå› æ­¤æŽ¨è��总是使用 sys.platform.startswith('aix')。 (由 M. Felt 在 bpo-36588 中贡献。)

  • 现在 PyEval_AcquireLock() å’Œ PyEval_AcquireThread() 当解释器正在最终化时被调用将会终结当å‰�线程,以使它们与 PyEval_RestoreThread(), Py_END_ALLOW_THREADS() å’Œ PyGILState_Ensure() ä¿�æŒ�一致。 如果ä¸�想è¦�æ­¤ç§�行为,请通过检测 _Py_IsFinalizing() 或 sys.is_finalizing() æ�¥ä¿�护该调用。 (由 Joannah Nanjekye 在 bpo-36475 中贡献。)

Python API 的�化¶

  • 在 Windows 上 os.getcwdb() 函数现在会使用 UTF-8 ç¼–ç �æ ¼å¼�而ä¸�是 ANSI 代ç �页:请å�‚看 PEP 529 了解具体原因。 该函数在 Windows 上ä¸�å†�被弃用。 (由 Victor Stinner 在 bpo-37412 中贡献。)

  • 现在 subprocess.Popen 在æŸ�些情况下会使用 os.posix_spawn() 以获得更好的性能。 在适用于 Linux çš„ Windows å­�系统和 QEMU 用户模拟器上,使用 os.posix_spawn() çš„ Popen 构造器ä¸�会å†�因为“找ä¸�到程åº�â€�这样的错误引å�‘异常。 而是让å­�进程失败并返回一个é�žé›¶çš„ returncode。 (由 Joannah Nanjekye å’Œ Victor Stinner 在 bpo-35537 中贡献。)

  • The preexec_fn argument of * subprocess.Popen is no longer compatible with subinterpreters. The use of the parameter in a subinterpreter now raises RuntimeError. (Contributed by Eric Snow in bpo-34651, modified by Christian Heimes in bpo-37951.)

  • imap.IMAP4.logout() 方法ä¸�会å†�é�™é»˜åœ°å¿½ç•¥ä»»æ„�异常。 (由 Victor Stinner 在 bpo-36348 中贡献。)

  • 函数 platform.popen() 已被移除,它自 Python 3.3 起就已被弃用:请改用 os.popen()。 (由 Victor Stinner 在 bpo-35345 中贡献。)

  • 当传入多模数æ�®æ—¶ statistics.mode() 函数ä¸�会å†�引å�‘异常。 它将改为返回在输入数æ�®ä¸­é�‡åˆ°çš„第一个模å¼�。 (由 Raymond Hettinger 在 bpo-35892 中贡献。)

  • tkinter.ttk.Treeview 类的 selection() 方法ä¸�å†�接å�—å�‚数。 带å�‚数调用该方法æ�¥æ”¹å�˜é€‰æ‹©åœ¨ Python 3.6 中已弃用。 请使用专门方法例如 selection_set() æ�¥æ”¹å�˜é€‰æ‹©ã€‚ (由 Serhiy Storchaka 在 bpo-31508 中贡献。)

  • xml.dom.minidom çš„ writexml(), toxml() å’Œ toprettyxml() 方法以å�Š xml.etree çš„ write() 方法现在会ä¿�留用户指定的属性顺åº�。 (由 Diego Rojas å’Œ Raymond Hettinger 在 bpo-34160 中贡献。)

  • 附带 'r' 旗标打开的 dbm.dumb æ•°æ�®åº“现在将是å�ªè¯»çš„。 如果数æ�®åº“ä¸�存在,附带 'r' å’Œ 'w' 旗标的 dbm.dumb.open() ä¸�会å†�创建数æ�®åº“。 (由 Serhiy Storchaka 在 bpo-32749 中贡献。)

  • 在 XMLParser çš„å­�类中定义的 doctype() 方法将ä¸�会å†�被调用,并将导致å�‘出 RuntimeWarning 而ä¸�是 DeprecationWarning。 请在目标上定义 doctype() 方法æ�¥å¤„ç�† XML doctype 声明。 (由 Serhiy Storchaka 在 bpo-29209 中贡献。)

  • 现在当自定义元类未在传给 type.__new__ 的命å��空间中æ��ä¾› __classcell__ å…¥å�£æ—¶å°†å¼•å�‘ RuntimeError。 在 Python 3.6--3.7 中是则是引å�‘ DeprecationWarning。 (由 Serhiy Storchaka 在 bpo-23722 中贡献。)

  • cProfile.Profile 类现在å�¯è¢«ç”¨ä½œä¸Šä¸‹æ–‡ç®¡ç�†å™¨ã€‚ (由 Scott Sanderson 在 bpo-29235 中贡献。)

  • shutil.copyfile(), shutil.copy(), shutil.copy2(), shutil.copytree() å’Œ shutil.move() 会使用平å�°ä¸“属的 "fast-copy" 系统调用(å�‚è§� ä¾�赖于具体平å�°çš„高效拷è´�æ“�作 一节)。

  • shutil.copyfile() 在 Windows 上的默认缓冲区大å°�从 16 KiB 改为 1 MiB。

  • PyGC_Head 结构已被完全改å�˜ã€‚ 所有接触到该结构的代ç �都应当被é‡�写。 (å�‚è§� bpo-33597。)

  • PyInterpreterState 结构已被移入 "internal" 头文件(特别是 Include/internal/pycore_pystate.h)。 ä¸�é€�明的 PyInterpreterState 作为仅有 API(以å�Šç¨³å®šç‰ˆ ABI)的一部分ä»�ç„¶å�¯ç”¨ã€‚ 文档指明该结构的任何字段都ä¸�是公有的,因此我们希望没人在使用它们。 但是,如果你确实ä¾�赖其中æŸ�一个或更多个ç§�有字段并且没有其他替代选项,则请开一个 BPO 问题。 我们将尽力帮助你进行调整(å�¯èƒ½åŒ…括å�‘公有 API 添加访问器函数)。 (å�‚è§� bpo-35886。)

  • 现在所有平å�°ä¸‹çš„ mmap.flush() 方法都会在æˆ�功时返回 None 并在错误时引å�‘异常。 之å‰�它的行为å�–决于具体平å�°ï¼š Windows 下会在æˆ�功时返回é�žé›¶å€¼ï¼›åœ¨å¤±è´¥æ—¶è¿”回零。 Unix 下会在æˆ�功时返回零;在失败时引å�‘错误。 (由 Berker Peksag 在 bpo-2122 中贡献。)

  • xml.dom.minidom å’Œ xml.sax 模å�—默认将ä¸�å†�处ç�†å¤–部实体。 (由 Christian Heimes 在 bpo-17239 中贡献。)

  • 从å�ªè¯»çš„ dbm æ•°æ�®åº“ (dbm.dumb, dbm.gnu 或 dbm.ndbm) 删除键将会引å�‘ error (dbm.dumb.error, dbm.gnu.error 或 dbm.ndbm.error) 而ä¸�是 KeyError。 (由 Xiang Zhang 在 bpo-33106 中贡献。)

  • 简化了字é�¢å€¼çš„ AST。 所有常é‡�将被表示为 ast.Constant 的实例。 实例化旧类 Num, Str, Bytes, NameConstant å’Œ Ellipsis 都将返回 Constant 的实例。 (由 Serhiy Storchaka 在 bpo-32892 中贡献。)

  • expanduser() 在 Windows 上现在改用 USERPROFILE 环境å�˜é‡�而ä¸�å†�使用 HOME,å�Žè€…通常ä¸�会为一般用户账户设置。 (由 Anthony Sottile 在 bpo-36264 中贡献。)

  • 异常 asyncio.CancelledError 现在继承自 BaseException 而ä¸�是 Exception 并且ä¸�å†�继承自 concurrent.futures.CancelledError。 (由 Yury Selivanov 在 bpo-32528 中贡献。)

  • 当使用 asyncio.Task 的实例时,函数 asyncio.wait_for() 现在会正确地等待撤销。 在此之å‰�当达到 timeout 时,它会被撤销并立å�³è¿”回。 (由 Elvis Pranskevichus 在 bpo-32751 中贡献。)

  • 当将 'socket' 作为 name å½¢å�‚传入时,函数 asyncio.BaseTransport.get_extra_info() 现在会返回一个å�¯å®‰å…¨ä½¿ç”¨çš„套接字对象。 (由 Yury Selivanov 在 bpo-37027 中贡献。)

  • asyncio.BufferedProtocol å·²ç»�晋级为稳定 API。

  • 在 Windows 上对扩展模å�—çš„ DLL ä¾�赖以å�Šé€šè¿‡ ctypes 加载的 DLL 的解æž�现在将更为安全。 å�ªæœ‰ç³»ç»Ÿè·¯å¾„ã€�包å�«ç›¸ä¿¡ DLL 或 PYD 文件的路径以å�Šé€šè¿‡ add_dll_directory() 添加的目录æ‰�会被作为加载时ä¾�èµ–çš„æ�œç´¢ä½�置。 特别地,PATH 和当å‰�工作目录将ä¸�å†�被使用,对它们的修改将ä¸�å†�对正常的 DLL è§£æž�产生影å“�。 如果你的应用ä¾�赖于这些机制,你应当先检查 add_dll_directory(),如果它存在就用它在加载你的库时添加你的 DLL 目录。 请注æ„� Windows 7 用户还需è¦�ç¡®ä¿� Windows 更新包 KB2533623 已安装(这一点也会由安装器进行验è¯�)。 (由 Steve Dower 在 bpo-36085 中贡献。)

  • å…³è�”到 pgen 的头文件和函数在其被纯 Python 实现å�–代å�Žå·²è¢«ç§»é™¤ã€‚ (由 Pablo Galindo 在 bpo-36623 中贡献。)

  • types.CodeType 在构造器的第二个ä½�置新增了一个形å�‚ (posonlyargcount) 以支æŒ�在 PEP 570 中定义的仅é™�ä½�ç½®å�‚数。 第一个å�‚æ•° (argcount) 现在表示ä½�ç½®å�‚数的总数é‡� (包括仅é™�ä½�ç½®å�‚æ•°)。 types.CodeType 中新增的 replace() 方法å�¯ç”¨äºŽè®©ä»£ç �支æŒ� future 特性。

  • hmac.new() çš„ digestmod å½¢å�‚ä¸�å†�默认使用 MD5 摘è¦�。

C API 的�化¶

  • PyCompilerFlags 结构体增加了一个新的 cf_feature_version 字段。 它应当被åˆ�始化为 PY_MINOR_VERSION。 该字段默认会被忽略,当且仅当在 cf_flags 中设置了 PyCF_ONLY_AST 旗标时æ‰�会被使用。 (由 Guido van Rossum 在 bpo-35766 中贡献。)

  • PyEval_ReInitThreads() 函数已被 C API 中移除。 它ä¸�应被显å¼�地调用:请改用 PyOS_AfterFork_Child()。 (由 Victor Stinner 在 bpo-36728 中贡献。)

  • 在 Unix 上,C 扩展ä¸�会å†�被链接到 libpython,但 Android å’Œ Cygwin 例外。 当 Python 被嵌入时,libpython ä¸�å�¯ä½¿ç”¨ RTLD_LOCAL 加载,而è¦�改用 RTLD_GLOBAL。 之å‰�使用 RTLD_LOCAL å·²ç»�ä¸�å�¯èƒ½åŠ è½½æœªé“¾æŽ¥åˆ° libpython çš„ C 扩展了,例如通过 Modules/Setup çš„ *shared* 部分构建的标准库 C 扩展。 (由 Victor Stinner 在 bpo-21536 中贡献。)

  • 在解æž�或构建值时(例如 PyArg_ParseTuple(), Py_BuildValue(), PyObject_CallFunction() 等等)使用形如 # 的格å¼�而ä¸�定义 PY_SSIZE_T_CLEAN 现在将会引å�‘ DeprecationWarning。 它将在 3.10 或 4.0 中被移除。 请å�‚阅 è§£æž�å�‚数并构建值å�˜é‡� 了解详情。 (由 Inada Naoki 在 bpo-36381 中贡献。)

  • 堆分é…�类型的实例(例如使用 PyType_FromSpec() 创建的实例)会ä¿�存一个对其类型对象的引用。 æ��å�‡è¿™äº›ç±»åž‹å¯¹è±¡å¼•用计数的æ“�作已从 PyType_GenericAlloc() 移至更低层级的函数 PyObject_Init() å’Œ PyObject_INIT()。 这使用通过This makes types created through PyType_FromSpec() 所创建类型的行为与管ç�†ä»£ç �中的其他类ä¿�æŒ�一致。

    ��分�类型 将��影�。

    在大部分情况下,这应该都�会有附带影�。 但是,在分�实例�手动��引用计数的类型(也许是为了绕过�洞)现在�能永远�会被销�。 ���这�情况,这些类需�在实例撤销分�期间在类型对象上调用 Py_DECREF。

    �正确地将这些类型移�到 3.8,请应用以下修改:

    • 在分é…�实例之å�Žåœ¨ç±»åž‹å¯¹è±¡ä¸Šç§»é™¤ Py_INCREF —— 如果有的è¯�。 è¿™å�¯èƒ½å�‘生在调用 PyObject_New, PyObject_NewVar, PyObject_GC_New(), PyObject_GC_NewVar() 或任何其他使用 PyObject_Init() 或 PyObject_INIT() 的自定义分é…�器之å�Žã€‚

      示例:

      static foo_struct *
      foo_new(PyObject *type) {
          foo_struct *foo = PyObject_GC_New(foo_struct, (PyTypeObject *) type);
          if (foo == NULL)
              return NULL;
      #if PY_VERSION_HEX < 0x03080000
          // Workaround for Python issue 35810; no longer necessary in Python 3.8
          PY_INCREF(type)
      #endif
          return foo;
      }
      
    • ç¡®ä¿�所有堆分é…�类型的自定义 tp_dealloc 函数会å‡�少类型的引用计数。

      示例:

      static void
      foo_dealloc(foo_struct *instance) {
          PyObject *type = Py_TYPE(instance);
          PyObject_GC_Del(instance);
      #if PY_VERSION_HEX >= 0x03080000
          // This was not needed before Python 3.8 (Python issue 35810)
          Py_DECREF(type);
      #endif
      }
      

    (由 Eddie Elizondo 在 bpo-35810 中贡献。)

  • Py_DEPRECATED() å®�å·²ç»�针对 MSVC 实现。 这个å®�现在必须放在符å�·å��称之å‰�。

    示例:

    Py_DEPRECATED(3.8) PyAPI_FUNC(int) Py_OldFunction(void);
    

    (由 Zackery Spytz 在 bpo-33407 中贡献。)

  • 解释器将ä¸�å†�å�‡è£…支æŒ�è·¨å�‘布版本的扩展类型二进制兼容性。 由第三方扩展模å�—所导出的 PyTypeObject 应当具有当å‰� Python 版本所è¦�求的所有槽ä½�,包括 tp_finalize (Py_TPFLAGS_HAVE_FINALIZE ä¸�å†�会在读å�– tp_finalize 之å‰�被检查)。

    (由 Antoine Pitrou 在 bpo-32388 中贡献。)

  • 函数 PyNode_AddChild() å’Œ PyParser_AddToken() 现在接å�—两个é¢�外的 int å�‚æ•° end_lineno å’Œ end_col_offset。

  • å…�许 MinGW 工具直接链接到 python38.dll çš„ libpython38.a 文件已ä¸�å†�包å�«äºŽæ ‡å‡†çš„ Windows 分å�‘包中。 如果你需è¦�此文件,å�¯ä½¿ç”¨ gendef å’Œ dlltool 工具æ�¥ç”Ÿæˆ�它,这些工具是 MinGW binutils 包的一部分:

    gendef - python38.dll > tmp.def
    dlltool --dllname python38.dll --def tmp.def --output-lib libpython38.a
    

    已安装的 pythonXY.dll 所在�置将�决于安装选项以� Windows 的版本和语言。 请�阅 在Windows上使用 Python 了解更多信�。 该结果库应当放在与 pythonXY.lib 相�的目录下,这通常是你的 Python 安装路径下的 libs 目录。

    (由 Steve Dower 在 bpo-37351 中贡献。)

CPython 字节�的改�¶

  • 解释器循环已通过将å�—堆栈展开逻辑移入编译器获得了简化。 编译器现在会å�‘出显å¼�指令æ�¥è°ƒæ•´å€¼å †æ ˆå¹¶ä¸º break, continue å’Œ return 调用清除代ç �。

    移除了�作� BREAK_LOOP, CONTINUE_LOOP, SETUP_LOOP 和 SETUP_EXCEPT。 添加了新的�作� ROT_FOUR, BEGIN_FINALLY, CALL_FINALLY 和 POP_FINALLY。 修改了 END_FINALLY 和 WITH_CLEANUP_START 的行为。

    (由 Mark Shannon, Antoine Pitrou 和 Serhiy Storchaka 在 bpo-17611 中贡献。)

  • 添加了新的æ“�作ç � END_ASYNC_FOR 用于处ç�†å½“等待 async for 循环的下一项时引å�‘的异常。 (由 Serhiy Storchaka 在 bpo-33041 中贡献。)

  • MAP_ADD 现在会预期值为栈的第一个元素而键为第二个元素。 作出此改å�˜ä»¥ä½¿å¾—字典推导å¼�能如 PEP 572 所æ��议的那样,键总是会在值之å‰�被求值。 (由 Jörn Heissler 在 bpo-35224 中贡献。)

演示和工具¶

添加了一个检测脚本用于对访问��的��方�进行计时: Tools/scripts/var_access_benchmark.py。 (由 Raymond Hettinger 在 bpo-35884 中贡献。)

以下是自 Python 3.3 以�性能��情况的总结:

Python version                       3.3     3.4     3.5     3.6     3.7     3.8
--------------                       ---     ---     ---     ---     ---     ---

Variable and attribute read access:
    read_local                       4.0     7.1     7.1     5.4     5.1     3.9
    read_nonlocal                    5.3     7.1     8.1     5.8     5.4     4.4
    read_global                     13.3    15.5    19.0    14.3    13.6     7.6
    read_builtin                    20.0    21.1    21.6    18.5    19.0     7.5
    read_classvar_from_class        20.5    25.6    26.5    20.7    19.5    18.4
    read_classvar_from_instance     18.5    22.8    23.5    18.8    17.1    16.4
    read_instancevar                26.8    32.4    33.1    28.0    26.3    25.4
    read_instancevar_slots          23.7    27.8    31.3    20.8    20.8    20.2
    read_namedtuple                 68.5    73.8    57.5    45.0    46.8    18.4
    read_boundmethod                29.8    37.6    37.9    29.6    26.9    27.7

Variable and attribute write access:
    write_local                      4.6     8.7     9.3     5.5     5.3     4.3
    write_nonlocal                   7.3    10.5    11.1     5.6     5.5     4.7
    write_global                    15.9    19.7    21.2    18.0    18.0    15.8
    write_classvar                  81.9    92.9    96.0   104.6   102.1    39.2
    write_instancevar               36.4    44.6    45.8    40.0    38.9    35.5
    write_instancevar_slots         28.7    35.6    36.1    27.3    26.6    25.7

Data structure read access:
    read_list                       19.2    24.2    24.5    20.8    20.8    19.0
    read_deque                      19.9    24.7    25.5    20.2    20.6    19.8
    read_dict                       19.7    24.3    25.7    22.3    23.0    21.0
    read_strdict                    17.9    22.6    24.3    19.5    21.2    18.9

Data structure write access:
    write_list                      21.2    27.1    28.5    22.5    21.6    20.0
    write_deque                     23.8    28.7    30.1    22.7    21.8    23.5
    write_dict                      25.9    31.4    33.3    29.3    29.2    24.7
    write_strdict                   22.9    28.4    29.9    27.5    25.2    23.1

Stack (or queue) operations:
    list_append_pop                144.2    93.4   112.7    75.4    74.2    50.8
    deque_append_pop                30.4    43.5    57.0    49.4    49.2    42.5
    deque_append_popleft            30.8    43.7    57.3    49.7    49.7    42.8

Timing loop:
    loop_overhead                    0.3     0.5     0.6     0.4     0.3     0.3

基准测试是在 Intel® Core™ i7-4960HQ 处�器 上�行从 python.org 获�的 macOS 64 �编译版得到的数�。 该基准测试脚本显示时间以纳秒为��。

Python 3.8.1 中的���化¶

出于��的安全性考�,asyncio.loop.create_datagram_endpoint() 的 reuse_address 形���被支�。 这是由 UDP 中的套接字选项 SO_REUSEADDR 的行为导致的。 更多细节请�阅 loop.create_datagram_endpoint() 的文档。 (由 Kyle Stanley, Antoine Pitrou 和 Yury Selivanov 在 bpo-37228 中贡献。。)

Python 3.8.2 中的���化¶

修�了 shutil.copytree() 的 ignore 回调中的回归问题。 现在该�数的类型已改回 str 和 List[str]。 (由 Manuel Barkhau 和 Giampaolo Rodola 在 gh-83571 中贡献。)

Python 3.8.3 中的���化¶

__future__ 模�中的 future 旗标常�值已被更新以防止与编译器旗标�生冲�。 在之�版本中 PyCF_ALLOW_TOP_LEVEL_AWAIT 与 CO_FUTURE_DIVISION 存在冲�。 (由 Batuhan Taskaya 在 gh-83743 中贡献。)

Python 3.8.8 中的���化¶

早先的 Python 版本�许使用 ; 和 & 作为 urllib.parse.parse_qs() 和 urllib.parse.parse_qsl() 中 query 形�的分隔键。 出于安全考虑,也为了�循更新的 W3C 推�设置,这已被改为��许�个分隔键,默认为 &。 这一改�还会影� cgi.parse() 和 cgi.parse_multipart() 因为它们在内部使用了�影�的函数。 �了解更多细节,请查看它们�自的文档。 (由 Adam Goldschmidt, Senthil Kumaran 和 Ken Jin 在 bpo-42967 中贡献。)

Python 3.8.9 中的���化¶

新的安全修正将 ftplib.FTP 的行为改�当设置被动数�通�时�信任远程�务器所��的 IPv4 地�。 我们会改为�用 ftp �务器的 IP 地�。 对于需�原先的行为的�常�代�,请在你的 FTP 实例上将 trust_server_pasv_ipv4_address 属性设为 True。 (�� gh-87451。)

Python 3.8.10 中的���化¶

macOS 11.0 (Big Sur) 与 Apple Silicon Mac 支�¶

对于 3.8.10,Python 现在支�在 macOS 11 (Big Sur) 和 Apple Silicon Mac (基于 ARM64 架构) 上构建和�行。 现在�供了一个新的通用构建形� universal2 能够在一组�执行文件上�时原生支� ARM64 和 Intel 64。 请注�对 "弱链接" 的支�,�以较新 macOS 版本为目标构建的二进制文件通过在�行时测试缺失特性的方�也能在较旧版本上正确�行,尚未被包括在本次对 Python 3.9 的��移�中;�支�更多的 macOS 版本,请继续以设定版本区间的最旧版本作为目标进行构建。

(最�由 Ronald Oussoren 和 Lawrence D'Anna 在 gh-85272 中贡献,由 FX Coudert 和 Eli Rykoff �供修正,并由 Maxime Bélanger 和 Ned Deily ��移�到 3.8)

Python 3.8.10 中的���化¶

urllib.parse¶

在 URL 中存在�行符或制表符,�能会导致�些形�的攻击。根� WHATWG 的规范更新了:rfc:3986, urllib.parse 中的解�器将从 URL 中移除 ASCII �行符 \n �\r 和 \t``字符,以防止这�攻击。将移除的字符由一个新的模�级��``urllib.parse._UNSAFE_URL_BYTES_TO_REMOVE 控制。(�阅 bpo-43882 )

Python 3.8.12 中的���化¶

Python API 的�化¶

从 Python 3.8.12 开始 ipaddress 模���接� IPv4 地�字符串中有任何�缀的零。 �缀的零有歧义且会被�些库解读为八进制数字。 例如旧版函数 socket.inet_aton() 就将�缀的零视为八进制数字。 最新 inet_pton() 的 glibc 实现则�接�任何�缀的零。

(最�由 Christian Heimes 在 bpo-36384 中贡献,并由 Achraf Merzouki �下移�到 3.8。)

3.8.14 中的��安全特性¶

使用�进制以外的底,如 2(二进制)�4�8(八进制)�16(�六进制)�32 以外作为基数在 int 和 str 之间进行转�,如果字符串形�的数字数�超过一个�制,会抛出 ValueError,以��因算法��而导致的潜在拒��务攻击。这是对 CVE-2020-10735 的缓解方案。这个�制�以通过环境���命令行旗标或 sys API 进行�置或�用。�� integer string conversion length limitation 文档。默认�制是字符串形�的 4300 �数字。

3.8.17 中的���化¶

tarfile¶

  • tarfile 中的æ��å�–方法和 shutil.unpack_archive() 都新增了 filter å�‚数以å…�许é™�制å�¯èƒ½ä»¤äººæ„�外或å�±é™©çš„ tar 特性,例如在目标目录之外创建文件。 相关细节å�‚è§� 解压缩过滤器。 在 Python 3.12 中,ä¸�带 filter å�‚数的用法将显示 DeprecationWarning。 在 Python 3.14 中,默认值将切æ�¢ä¸º 'data'。 (由 Petr Viktorin 在 PEP 706 中贡献。)