python 3.8的新功能

编辑

雷蒙德·赫廷格

本文将解释Python 3.8与3.7相比的新特性。有关详细信息,请参见 changelog .

总结——发布亮点

新特点

赋值表达式

有新的语法 := 将值作为较大表达式的一部分分配给变量的。它被亲切地称为“海象操作员”,因为它类似于 the eyes and tusks of a walrus .

在本例中,赋值表达式有助于避免调用 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循环,该运算符也很有用,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]

尽量限制使用walrus操作符来清理减少复杂性和提高可读性的案例。

PEP 572 完整描述。

(艾米丽·莫豪斯在 bpo-35224

仅位置参数

有一个新的函数参数语法 / 以指示某些函数参数必须按位置指定,并且不能用作关键字参数。这是由 help() 对于用Larry Hastings注释的C函数 Argument Clinic 工具。

在下面的示例中,参数 ab 只是位置性的,而 cd 可以是位置或关键字,并且 ef 必须是关键字:

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上,除了Android和Cygwin外,C扩展不再链接到libpython。现在,静态链接的Python可以加载使用共享库Python构建的C扩展。(由Victor Stinner在 bpo-21536

在UNIX上,当以调试模式构建python时,import现在还查找以发布模式编译的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配置 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 s、 f字符串,如 f'{{expr=}}' 将展开到表达式的文本、等号,然后是求值表达式的表示形式。例如:

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

通常 f-string format specifiers 允许对表达式结果的显示方式进行更多控制:

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

(埃里克诉史密斯和拉里·黑斯廷斯在 bpo-36817

PEP 578:Python运行时审计挂钩

PEP添加了一个审计钩子和已验证的开放钩子。两者都可以从Python和本机代码中获得,允许使用纯Python代码编写的应用程序和框架利用额外的通知,同时还允许嵌入程序或系统管理员在始终启用审计的情况下部署Python构建。

PEP 578 详细信息。

PEP 587:python初始化配置

这个 PEP 587 添加一个新的C API来配置python初始化,从而对整个配置提供更好的控制和更好的错误报告。

新结构:

新功能:

这个政治公众人物还补充说 _PyRuntimeState.preconfig (PyPreConfig 类型)和 PyInterpreterState.config (PyConfig 类型)这些内部结构的字段。 PyInterpreterState.config 成为新的引用配置,替换全局配置变量和其他私有变量。

Python Initialization Configuration 用于文档。

PEP 587 完整描述。

(由Victor Stinner在 bpo-36763

PEP 590:Vectorcall:CPython的快速调用协议

矢量调用协议 添加到Python/C API中。它的目的是将已经为各种类完成的现有优化形式化。任何实现可调用的静态类型都可以使用此协议。

这是暂时的。目的是在Python3.9中完全公开它。

PEP 590 完整描述。

(由杰罗恩德梅耶,马克香农和彼得维克托林在 bpo-36974

带带外数据缓冲区的pickle协议5

什么时候? pickle 用于在python进程之间传输大数据,为了利用多核或多机处理,通过减少内存副本以及可能应用自定义技术(如数据相关压缩)来优化传输非常重要。

这个 pickle 协议5引入了对带外缓冲区的支持,其中 PEP 3118 -根据通信层的判断,兼容数据可以与主pickle流分开传输。

PEP 574 完整描述。

(由Antoine Pitrou在 bpo-36785

其他语言更改

  • A continue 声明在中是非法的 finally 由于实现有问题而导致的子句。在python 3.8中,这个限制被解除了。(Serhiy Storchaka在 bpo-32489

  • 这个 boolintfractions.Fraction 类型现在有一个 as_integer_ratio() 这种方法在 floatdecimal.Decimal . 这个小的API扩展使得可以编写 numerator, denominator = x.as_integer_ratio() 并让它跨多个数字类型工作。(作者:Lisa Roach in) bpo-33073 还有雷蒙德·赫廷格 bpo-37819

  • 建筑工人 intfloatcomplex 现在将使用 __index__() 特殊方法(如有)和相应方法 __int__()__float__()__complex__() 不可用。(Serhiy Storchaka在 bpo-20092

  • 增加了对 \N{{name}} 逃逸 regular expressions ::

    >>> 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) 不再允许。它从未打算在关键字参数赋值项的左侧允许超过一个裸名称。(本杰明·彼得森在 bpo-34641

  • 广义可拓解包 yieldreturn 语句不再需要括括号。这就带来了 产量返回 语法与正常赋值语法更加一致:

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

    (作者大卫·卡斯伯特和乔丹·查普曼 bpo-32117

  • 当代码中缺少逗号时,例如 [(10, 20) (30, 40)] ,编译器将显示 SyntaxWarning 有个有用的建议。这比仅仅拥有一个 TypeError 表示第一个元组不可调用。(塞尔希斯托查卡在 bpo-15248

  • 子类之间的算术运算 datetime.datedatetime.datetimedatetime.timedelta 对象现在返回子类的一个实例,而不是基类。这还影响其实现(直接或间接)使用的操作的返回类型 datetime.timedelta 算术,如 astimezone() . (由Paul Ganssle在 bpo-32417

  • 当python解释器被ctrl-c(sigint)中断时, KeyboardInterrupt 未捕获异常,python进程现在通过sigint信号或使用正确的退出代码退出,这样调用进程就可以检测到它是由于ctrl-c而死亡的。posix和windows上的shell使用此方法在交互会话中正确终止脚本。(由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 ,以及其他负指数的逆幂。例如,要计算 modular multiplicative inverse 在38的137模中,写:

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

    模逆产生于 linear Diophantine equations . 例如,要查找 4258𝑥 + 147𝑦 = 369 ,首先重写为 4258𝑥 369 (mod 147) 然后解决:

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

    (马克·狄金森在 bpo-36027

  • Dict理解已与Dict文本同步,以便首先计算键,然后计算值:

    >>> # 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'}
    

    (作者:海斯勒 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_linenoend_col_offset 属性,提供节点末端的精确位置。(这仅适用于 linenocol_offset 属性。)

新功能 ast.get_source_segment() 返回特定ast节点的源代码。

(伊万·列夫基夫斯基于 bpo-33416

这个 ast.parse() 函数有一些新标志:

  • type_comments=True 使其返回 PEP 484PEP 526 与某些ast节点关联的类型注释;

  • mode='func_type' 可用于分析 PEP 484 “签名类型注释”(返回函数定义ast节点);

  • feature_version=(3, N) 允许指定较早的Python3版本。例如, feature_version=(3, 4) 会治疗 asyncawait 作为非保留字。

(作者:Guido van Rossum in) bpo-35766

asyncio

asyncio.run() 已从临时API升级为稳定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() 应该是运行异步程序的首选方式。

(由Yury Selivanov在 bpo-32314

运行 python -m asyncio 启动本机异步复制。这允许对具有顶级 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 . (亚历克斯·格伦霍姆在 bpo-36999

现在可以通过传递 name 关键字参数 asyncio.create_task()create_task() 事件循环方法,或通过调用 set_name() 任务对象的方法。任务名称在 repr() 的输出 asyncio.Task 也可以使用 get_name() 方法。(亚历克斯·格伦霍姆在 bpo-34270

为添加了支持 Happy Eyeballsasyncio.loop.create_connection() . 要指定行为,添加了两个新参数: happy_eyeballs_delay交错 . 开心眼球算法通过尝试同时使用IPv4和IPv6连接来提高支持IPv4和IPv6的应用程序的响应能力。(驻英国大使托斯特罗伊德供稿) bpo-33530

建筑材料

这个 compile() 内置的已改进以接受 ast.PyCF_ALLOW_TOP_LEVEL_AWAIT 旗帜。当这个新的旗子通过时, compile() 将允许顶级 awaitasync forasync with 通常被认为是无效语法的构造。用标记的异步代码对象 CO_COROUTINE 然后可以返回标志。(马蒂亚斯·布森尼尔在 bpo-34616

收藏

这个 _asdict() 方法 collections.namedtuple() 现在返回 dict 而不是 collections.OrderedDict . 这是因为自Python3.7以来,常规的dict已经保证了排序。如果 OrderedDict 如果需要,建议的补救措施是将结果强制转换为所需类型: OrderedDict(nt._asdict()) . (由Raymond Hettinger在 bpo-35864

cProfile

这个 cProfile.Profile 类现在可以用作上下文管理器。通过运行以下命令分析代码块:

import cProfile

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

(作者:斯科特·桑德森 bpo-29235

csv

这个 csv.DictReader 现在返回的实例 dict 而不是 collections.OrderedDict . 该工具现在速度更快,占用的内存更少,同时仍保持字段顺序。(作者:迈克尔·塞利克 bpo-34003

curses

为基础ncurses库添加了一个保存结构化版本信息的新变量: ncurses_version . (Serhiy Storchaka在 bpo-31680

C型

在Windows上, CDLL 子类现在接受 温德模式 用于指定基础标志的参数 LoadLibraryEx 打电话。默认标志设置为仅从受信任位置加载dll依赖项,包括存储dll的路径(如果使用完整或部分路径加载初始dll)和由添加的路径 add_dll_directory() . (史蒂夫道尔供稿 bpo-36085

日期时间

添加了新的备用构造函数 datetime.date.fromisocalendar()datetime.datetime.fromisocalendar() ,哪个构造 datedatetime 分别来自ISO year、week number和weekday的对象;它们与每个类的 isocalendar 方法。(由Paul Ganssle在 bpo-36004

功能工具

functools.lru_cache() 现在可以用作直接的装饰器,而不是作为返回装饰器的函数。所以现在这两个都支持:

@lru_cache
def f(x):
    ...

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

(由Raymond Hettinger在 bpo-36772

增加了一个新的 functools.cached_property() decorator,用于实例生命周期中缓存的计算属性。:

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() 将方法转换为 generic functions 使用 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]

(作者伊森·史密斯 bpo-32380

GC

get_objects() 现在可以接收可选 一代 表示从中获取对象的生成的参数。(Pablo Galindo于 bpo-36016

获取文本

补充 pgettext() 以及它的变体。(由Franz Glasner、Ric Araujo和Cheryl Sabella在 bpo-2504

GZIP

增加了 mtime 参数到 gzip.compress() 用于可复制输出。(郭慈teo于年供稿) bpo-34898

A BadGzipFile 现在引发异常而不是 OSError 对于某些类型的无效或损坏的gzip文件。(由菲利普·格鲁兹基、米歇尔·奥尔和扎克利·斯皮茨在 bpo-6584

空闲和空闲

N行上的输出(默认为50)被压缩为一个按钮。n可以在设置对话框的常规页面的pyshell部分更改。用鼠标右键单击输出可以压缩的行更少,但也可能更长。通过双击按钮或右键单击按钮进入剪贴板或单独的窗口,可以就地扩展压缩输出。(由Tal Einat在 bpo-1529353

将“运行自定义”添加到“运行”菜单以运行具有自定义设置的模块。输入的任何命令行参数都将添加到sys.argv。它们也会重新出现在下一次自定义运行的框中。也可以抑制正常的Shell主模块重启。(由Cheryl Sabella、Terry Jan Reedy和其他 bpo-5680bpo-37627

为空闲编辑器窗口添加了可选行号。除非在“配置”对话框的“常规”选项卡中另有设置,否则窗口将不带行号打开。现有窗口的行号将显示并隐藏在“选项”菜单中。(Tal Einat和Saimadhav Heblikar在 bpo-17535

OS本机编码现在用于Python字符串和Tcl对象之间的转换。这允许IDLE处理emoji和其他非BMP字符。这些字符可以显示、复制并粘贴到剪贴板或从剪贴板粘贴。将字符串从Tcl转换到Python再转换回Python现在永远不会失败。(许多人为此工作了八年,但这个问题终于在年由塞尔希斯托尔恰卡解决了。) bpo-13153

3.8.1新增:

关闭闪烁选项。(作者:Zackery Spytz bpo-4603

Escape键现在关闭空闲完成窗口。(作者:Johnny Najera bpo-38944

以上更改已返回到3.7维护版本。

向模块名称完成列表添加关键字。(作者:Terry J.Reedy bpo-37765

检查

这个 inspect.getdoc() 函数现在可以找到 __slots__ 如果该属性是 dict 其中值是docstring。这提供了类似于我们已有的文档选项 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

输入输出

在开发模式下 (-X env )在调试构建中, io.IOBase 如果 close() 方法失败。默认情况下,在发布版本中会自动忽略该异常。(由Victor Stinner在 bpo-18748

迭代工具

这个 itertools.accumulate() 函数添加了一个选项 最初的 用于指定初始值的关键字参数:

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

(作者:Lisa Roach in) bpo-34659

json.tool

添加选项 --json-lines 将每个输入行解析为单独的JSON对象。(洪伟鹏供稿 bpo-31553

登录中

增加了一个 关键字参数 logging.basicConfig() 如果设置为true,则在执行其他参数指定的配置之前,将删除并关闭附加到根记录器的任何现有处理程序。

这解决了一个长期存在的问题。一次伐木工人或 基本配置() 已经打过电话,后来打给 基本配置() 被默默地忽略了。这使得使用交互式提示符或Jupyter笔记本更新、试验或教授各种日志配置选项变得困难。

(Raymond Hettinger建议,Dong hee Na实施,Vinay Sajip in审核) bpo-33897

数学

新增功能 math.dist() 用于计算两点之间的欧氏距离。(由Raymond Hettinger在 bpo-33089

扩大了 math.hypot() 函数处理多个维度。以前,它只支持二维案例。(由Raymond Hettinger在 bpo-33089

新增功能, math.prod() ,类似于 sum() 返回“start”值(默认值:1)乘以iterable的数字:

>>> 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-37128bpo-37178bpo-35431

添加了一个新函数 math.isqrt() 用于计算不转换为浮点的精确整数平方根。新函数支持任意大的整数。它比 floor(sqrt(n)) 但比 math.sqrt() ::

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

(马克·狄金森在 bpo-36887

函数 math.factorial() 不再接受非int-like的参数。(Pablo Galindo在 bpo-33083

MMAP

这个 mmap.mmap 班级现在有一个 madvise() 访问的方法 madvise() 系统调用。(由扎克利·斯皮茨在 bpo-32941

多重处理

新增 multiprocessing.shared_memory 模块。(作者:Davin Potts in) bpo-35813

在MacOS上, 产卵 默认情况下,现在使用Start方法。(由Victor Stinner在 bpo-33725

操作系统

新增功能 add_dll_directory() 在Windows上,用于在导入扩展模块或使用加载DLL时为本机依赖项提供其他搜索路径 ctypes . (史蒂夫道尔供稿 bpo-36085

一个新的 os.memfd_create() 添加了函数来包装 memfd_create() 系统调用。(由扎克利·斯皮茨和克里斯蒂安·海姆斯在 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() 现在可以将连接视为链接。

(史蒂夫道尔供稿 bpo-37834

os.path

os.path 返回布尔结果的函数 exists()lexists()isdir()isfile()islink()ismount() 现在回来 False 而不是提高 ValueError 或其子类 UnicodeEncodeErrorUnicodeDecodeError 对于包含在操作系统级别不可显示的字符或字节的路径。(Serhiy Storchaka在 bpo-33721

expanduser() 在Windows上,现在更喜欢 USERPROFILE 环境变量且不使用 HOME ,这通常不为常规用户帐户设置。(安东尼·索蒂尔供稿 bpo-36264

isdir() 在Windows上不再返回 True 指向不存在的目录的链接。

realpath() 在Windows上,现在解析重新分析点,包括符号链接和目录连接。

(史蒂夫道尔供稿 bpo-37834

pathlib

pathlib.Path 返回布尔结果的方法 exists()is_dir()is_file()is_mount()is_symlink()is_block_device()is_char_device()is_fifo()is_socket() 现在回来 False 而不是提高 ValueError 或其子类 UnicodeEncodeError 对于包含OS级别不可显示字符的路径。(Serhiy Storchaka在 bpo-33721

补充 pathlib.Path.link_to() 创建指向路径的硬链接。(由Joannah Nanjekye在 bpo-26978

泡菜

pickle 扩展子类化C优化 Pickler 现在可以通过定义特殊的 reducer_override() 方法。(Pierre Glaser和Olivier Grisel在 bpo-35900

普利斯利布

新增 plistlib.UID 并支持读写nskeyedarchive编码的二进制plist。(由Jon Janzen在 bpo-26707

印记

这个 pprint 模块添加了 sort_dicts 多个函数的参数。默认情况下,这些函数在呈现或打印之前继续对词典进行排序。但是,如果 sort_dicts 如果设置为false,则字典将保留插入键的顺序。这对于在调试期间与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 in供稿) bpo-30670

py_compile

py_compile.compile() 现在支持静默模式。(由Joannah Nanjekye在 bpo-22640

施莱克斯

新的 shlex.join() 函数用作 shlex.split() . (由Bo Bayles于 bpo-32102

舒蒂尔

shutil.copytree() 现在接受新的 dirs_exist_ok 关键字参数。(乔希·布朗森在 bpo-20849

shutil.make_archive() 现在默认为现代pax(posix.1-2001)格式的新档案馆,以提高可移植性和标准一致性,继承了从相应的变化到 tarfile 模块。(C.A.M.Gerlach在 bpo-30661

shutil.rmtree() 在Windows上,现在删除目录连接而不首先递归地删除其内容。(史蒂夫道尔供稿 bpo-37834

Socket

补充 create_server()has_dualstack_ipv6() 在创建服务器套接字时自动执行所需任务的便利功能,包括在同一套接字上同时接受IPv4和IPv6连接。(吉安波洛·罗多拉于年撰稿) bpo-17561

这个 socket.if_nameindex()socket.if_nametoindex()socket.if_indextoname() 功能已在Windows上实现。(由扎克利·斯皮茨在 bpo-37007

SSL

补充 post_handshake_auth 启用和 verify_client_post_handshake() 启动TLS 1.3握手后身份验证。(由Christian Heimes在 bpo-34670

统计学

补充 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.unraisablehook() 函数,它可以被重写以控制如何处理“不可评估的异常”。当发生异常时调用它,但Python无法处理它。例如,当析构函数引发异常或在垃圾收集期间 (gc.collect() )(由Victor Stinner在 bpo-36829

tarfile

这个 tarfile 模块现在默认为新档案的现代PAX(posix.1-2001)格式,而不是以前的GNU特定格式。这通过标准化和可扩展格式的一致编码(UTF-8)提高了跨平台的可移植性,并提供了其他一些好处。(C.A.M.Gerlach在 bpo-36268

线程加工

添加新的 threading.excepthook() 处理未绘制的函数 threading.Thread.run() 例外。它可以被重写以控制未捕获的程度 threading.Thread.run() 处理异常。(由Victor Stinner在 bpo-1230540

添加新的 threading.get_native_id() 函数和 native_id 属性 threading.Thread 上课。它们返回由内核分配的当前线程的本机完整线程ID。此功能仅在某些平台上可用,请参见 get_native_id 更多信息。(作者杰克·特斯勒 bpo-36084

令牌化

这个 tokenize 模块现在隐式地发出 NEWLINE 当输入没有尾随新行时提供标记。这种行为现在与C记号赋予器在内部所做的相匹配。(安马尔·阿斯卡尔在 bpo-33899

tkinter

添加方法 selection_from()selection_present()selection_range()selection_to()tkinter.Spinbox 类。(朱丽叶·蒙塞尔在 bpo-34829

添加的方法 moveto()tkinter.Canvas 类。(朱丽叶·蒙塞尔在 bpo-23831

这个 tkinter.PhotoImage 现在上课了 transparency_get()transparency_set() 方法。(由扎克利·斯皮茨在 bpo-25451

时间

新增时钟 CLOCK_UPTIME_RAW 对于MacOS 10.12。(由Joannah Nanjekye在 bpo-35702

typing

这个 typing 模块包含了几个新功能:

unicodedata

这个 unicodedata 模块已升级为使用 Unicode 12.1.0 释放。

新功能 is_normalized() 可用于验证字符串是否为特定的正常形式,通常比实际规范化字符串快得多。(作者:Max Belanger、David Euresti和Greg Price bpo-32285bpo-37966

单元测试

补充 AsyncMock 支持的异步版本 Mock . 还添加了适当的用于测试的新断言函数。(作者:Lisa Roach in) bpo-26467

补充 addModuleCleanup()addClassCleanup() 用于支持清理的UnitTest setUpModule()setUpClass() . (莉萨·罗奇在 bpo-24412

几个mock assert函数现在也会在失败时打印实际调用的列表。(由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下激活虚拟环境的所有平台上的脚本。(布雷特·坎农在 bpo-32718

韦克里夫

由返回的代理对象 weakref.proxy() 现在支持矩阵乘法运算符 @@= 除了其他数字运算符。(马克·狄金森在 bpo-36669

XML

作为对DTD和外部实体检索的缓解措施, xml.dom.minidomxml.sax 默认情况下,模块不再处理外部实体。(由Christian Heimes在 bpo-17239

这个 .find*() 方法在 xml.etree.ElementTree 模块支持通配符搜索,如 {{*}}tag 它忽略了名称空间和 {{namespace}}* 返回给定命名空间中的所有标记。(由Stefan Behnel在 bpo-28238

这个 xml.etree.ElementTree 模块提供新功能 –xml.etree.ElementTree.canonicalize() 实现C14N 2.0。(由Stefan Behnel在 bpo-13611

的目标对象 xml.etree.ElementTree.XMLParser 无法通过新的回调方法接收命名空间声明事件 start_ns()end_ns() . 另外, xml.etree.ElementTree.TreeBuilder 可以将目标配置为处理有关注释和处理指令的事件,以将它们包括在生成的树中。(由Stefan Behnel在 bpo-36676bpo-36673

xmlrpc

xmlrpc.client.ServerProxy 现在支持可选 报头 要随每个请求一起发送的一系列HTTP头的关键字参数。除此之外,这使得从默认的基本身份验证升级到更快的会话身份验证成为可能。(Cédric Krier在 bpo-35153

优化

  • 这个 subprocess 模块现在可以使用 os.posix_spawn() 在某些情况下,可以提高性能。目前,只有在满足所有这些条件的情况下,它才用于MacOS和Linux(使用glibc 2.24或更高版本):

    • close_fds 是假的;

    • preexec_fnpass_fdscwdstart_new_session 未设置参数;

    • 这个 可执行文件 路径包含一个目录。

    (由Joannah Nanjekye和Victor Stinner在 bpo-35537

  • shutil.copyfile()shutil.copy()shutil.copy2()shutil.copytree()shutil.move() 在Linux和MacOS上使用特定于平台的“快速复制”系统调用,以便更有效地复制文件。”“快速复制”是指复制操作发生在内核中,避免在python中使用“outdd.write(infd.read())`”中的用户空间缓冲区。在Windows上 shutil.copyfile() 使用更大的默认缓冲区大小(1 mib而不是16 kib)和 memoryview() -基于的变量 shutil.copyfileobj() 使用。在同一个分区中复制512 mib文件的速度在Linux上约为+26%,在MacOS上为+50%,在Windows上为+40%。此外,CPU周期消耗更少。见 依赖平台的高效复制操作 章节。(吉安波洛·罗多拉于年撰稿) bpo-33671

  • shutil.copytree() 使用 os.scandir() 函数和依赖于它的所有复制函数使用缓存 os.stat() 价值观。复制包含8000个文件的目录的速度在Linux上大约是+9%,在Windows上是+20%,在Windows SMB共享上是+30%。还有 os.stat() 系统调用减少了38%,使 shutil.copytree() 尤其是在网络文件系统上。(吉安波洛·罗多拉于年撰稿) bpo-33695

  • 中的默认协议 pickle 模块现在是协议4,在Python3.4中首次引入。与自Python3.0以来提供的协议3相比,它提供了更好的性能和更小的大小。

  • 去掉一个 Py_ssize_t 成员来自 PyGC_Head . 所有GC跟踪的对象(例如tuple、list、dict)的大小都减少了4或8个字节。(Inada Naoki在 bpo-33597

  • uuid.UUID 现在使用 __slots__ 以减少其内存占用。(沃特·布尔斯特利和塔尔·艾纳特于 bpo-30977

  • 改进的性能 operator.itemgetter() 到33%点。优化了参数处理,并将单个非负整数索引的常见情况的快速路径添加到元组中(这是标准库中的典型用例)。(由Raymond Hettinger在 bpo-35664

  • 加快locale查找速度 collections.namedtuple() . 它们现在的速度比以前快了两倍多,这使得它们成为Python中最快的实例变量查找形式。(由Raymond Hettinger、Pablo Galindo和Joe Jevnik,Serhiy Storchaka于 bpo-32492

  • 这个 list 如果输入iterable的长度已知(输入实现),则构造函数不会过度分配内部项缓冲区 __len__ )这使得创建的列表平均减少了12%。(由Raymond Hettinger和Pablo Galindo在 bpo-33234

  • 类变量写入速度增加了一倍。当一个非dunder属性被更新时,有一个不必要的调用来更新slots。(由Stefan Behnel、Pablo Galindo Salgado、Raymond Hettinger、Neil Schemenauer和Serhiy Storchaka在 bpo-36012

  • 减少了转换传递给许多内置函数和方法的参数的开销。这使得调用一些简单的内置函数和方法的速度加快了20%-50%。(Serhiy Storchaka在 bpo-23867bpo-35582bpo-36127

  • LOAD_GLOBAL 指令现在使用新的“每操作码缓存”机制。现在大约快了40%。(由Yury Selivanov和Inada Naoki在 bpo-26219

构建和C API更改

  • 违约 sys.abiflags 变成空字符串: m pymalloc的标志变得无用(具有和不具有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 成为 .cpython-38-x86_64-linux-gnu.so 在Python 3.8中。

  • 头文件已经重新组织,以便更好地分离不同类型的API:

    • Include/*.h 应该是可移植的公共稳定C API。

    • Include/cpython/*.h 应该是特定于cpython的不稳定的C API;公共API,前面带有一些私有API _Py_PY .

    • Include/internal/*.h 是私有的内部C API,非常特定于CPython。此API没有向后兼容性保证,不应在CPython之外使用。它只针对非常特殊的需求(如调试程序和概要文件)公开,这些需求必须在不调用函数的情况下访问cpython内部。此API现在由安装 make install .

    (由Victor Stinner在 bpo-35134bpo-35081 ,由Eric Snow在Python3.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.distModules/Setup 已删除。以前,在更新cpython源码树时,必须手动复制 Modules/Setup.dist (在源码树中)到 Modules/Setup (在构建树中)以反映上游的任何更改。这对打包者来说是一个小的好处,但代价是在cpython开发之后开发人员经常遇到麻烦,因为忘记复制文件可能会导致构建失败。

    现在构建系统总是从 Modules/Setup 在源码树中。我们鼓励那些想要定制该文件的人在cpython的Git分支或作为补丁文件来维护他们的更改,就像他们对源代码树的任何其他更改一样。

    (由Antoine Pitrou在 bpo-32430

  • 将python数字转换为C整数的函数 PyLong_AsLong() 和参数解析函数 PyArg_ParseTuple() 使用整数转换格式单位,如 'i' 现在将使用 __index__() 特殊方法而不是 __int__() ,如果有。对于具有 __int__() 方法,但没有 __index__() 方法(类) DecimalFractionPyNumber_Check() 现在将返回 1 用于实现对象 __index__() . PyNumber_Long()PyNumber_Float()PyFloat_AsDouble() 现在也可以使用 __index__() 方法(如果可用)。(Serhiy Storchaka在 bpo-36048bpo-20092

  • 堆分配的类型对象现在将增加其引用计数 PyObject_Init() (及其并行宏 PyObject_INIT 而不是在 PyType_GenericAlloc() . 可能需要调整修改实例分配或释放的类型。(由Eddie Elizondo在 bpo-35810

  • 新功能 PyCode_NewWithPosOnlyArgs() 允许创建类似 PyCode_New() ,但加一个 POSONLYARG计数 用于指示仅位置参数的数目的参数。(Pablo Galindo在 bpo-37221

  • Py_SetPath() 现在集 sys.executable 到程序完整路径 (Py_GetProgramFullPath() )而不是程序名 (Py_GetProgramName() )(由Victor Stinner在 bpo-38234

已弃用

API和功能删除

以下特性和API已从Python3.8中删除:

  • 从Python 3.3开始,从 collections 已弃用,导入应从 collections.abc . 能够从集合中导入在3.8中标记为删除,但已延迟到3.9。(见 bpo-36952

  • 这个 macpath python 3.7中不推荐使用的模块已被删除。(由Victor Stinner在 bpo-35471

  • 函数 platform.popen() 自Python 3.3:use以来一直不推荐使用 os.popen() 相反。(由Victor Stinner在 bpo-35345

  • 函数 time.clock() 自Python 3.3:use以来一直不推荐使用 time.perf_counter()time.process_time() 相反,根据你的要求,要有明确的行为。(马蒂亚斯·布森尼尔在 bpo-36895

  • 这个 pyvenv 已删除脚本以支持 python3.8 -m venv 以帮助消除关于Python解释器 pyvenv 脚本绑定到。(布雷特·坎农在 bpo-25427

  • parse_qsparse_qslescapecgi 模块。在Python3.2或更高版本中,它们已被弃用。它们应该从 urllib.parsehtml 而不是模块。

  • filemode 函数从 tarfile 模块。自python 3.3以来,它没有被记录和弃用。

  • 这个 XMLParser 构造函数不再接受 html 参数。它从未产生过效果,在Python3.4中被弃用。所有其他参数现在都是 keyword-only . (Serhiy Storchaka在 bpo-29209

  • 移除 doctype() 方法 XMLParser . (Serhiy Storchaka在 bpo-29209

  • “unicode_internal”编解码器已删除。(Inada Naoki在 bpo-36297

  • 这个 CacheStatement 的对象 sqlite3 模块不向用户公开。(由Aviv Palivoda在 bpo-30262

  • 这个 bufsize 的关键字参数 fileinput.input()fileinput.FileInput() 由于python 3.6已被删除,它被忽略并弃用。 bpo-36952 (由Matthias Bussonnier提供。)

  • 功能 sys.set_coroutine_wrapper()sys.get_coroutine_wrapper() python 3.7中已弃用,已删除; bpo-36933 (由Matthias Bussonnier提供。)

移植到python 3.8

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

python行为的变化

  • 产量表达式(两个 yieldyield from 从句)现在在理解和生成器表达式中是不允许的(最左边的iterable表达式除外) for 条款)。(Serhiy Storchaka在 bpo-10544

  • 编译器现在生成一个 SyntaxWarning 身份检查时 (isis not )与某些类型的文字(例如字符串、数字)一起使用。在CPython中,这些测试通常是意外工作的,但语言规范并不能保证这些测试有效 (==!= 相反。(Serhiy Storchaka在 bpo-34850

  • 在某些情况下,CPython解释器可以接受异常。在Python3.8中,这种情况很少发生。特别是,从类型字典获取属性时引发的异常不再被忽略。(塞尔希斯托查卡在 bpo-35459

  • 远离的 __str__ 内置类型的实现 boolintfloatcomplex 以及标准库中的一些类。他们现在继承了 __str__()object . 因此,定义 __repr__() 这些类的子类中的方法将影响它们的字符串表示。(塞尔希斯托查卡在 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 in) bpo-36475

python api中的更改

  • 这个 os.getcwdb() 函数现在在Windows上使用UTF-8编码,而不是ANSI代码页:请参见 PEP 529 理由是。在Windows上不再推荐使用该函数。(由Victor Stinner在 bpo-37412

  • subprocess.Popen 现在可以使用 os.posix_spawn() 在某些情况下为了更好的表现。在用于Linux和QEMU用户仿真的Windows子系统上 Popen 构造函数使用 os.posix_spawn() 不再对“缺少程序”之类的错误引发异常。相反,子进程失败,出现非零 returncode . (由Joannah Nanjekye和Victor Stinner在 bpo-35537

  • 这个 preexec_fn 论证* subprocess.Popen 不再与子解释程序兼容。在子解释器中使用参数现在引发 RuntimeError . (艾瑞克·斯诺供稿 bpo-34651 ,由Christian Heimes在 bpo-37951

  • 这个 imap.IMAP4.logout() 方法不再自动忽略任意异常。(作者:Victor Stinner in) bpo-36348

  • 函数 platform.popen() 自Python 3.3:use以来一直不推荐使用 os.popen() 相反。(由Victor Stinner在 bpo-35345

  • 这个 statistics.mode() 函数在给定多模数据时不再引发异常。相反,它返回在输入数据中遇到的第一个模式。(由Raymond Hettinger在 bpo-35892

  • 这个 selection() 方法 tkinter.ttk.Treeview 类不再接受参数。在python 3.6中,不赞成将它与更改选择的参数一起使用。使用专门的方法,比如 selection_set() 用于更改选择。(Serhiy Storchaka在 bpo-31508

  • 这个 writexml()toxml()toprettyxml() 方法 xml.dom.minidomwrite() 方法 xml.etree ,现在保留用户指定的属性顺序。(Diego Rojas和Raymond Hettinger在 bpo-34160

  • A dbm.dumb 用标志打开的数据库 'r' 现在是只读的。 dbm.dumb.open() 带旗 'r''w' 如果数据库不存在,则不再创建它。(Serhiy Storchaka在 bpo-32749

  • 这个 doctype() 在的子类中定义的方法 XMLParser 将不再被调用并将发出 RuntimeWarning 而不是 DeprecationWarning . 定义 doctype() 用于处理XML doctype声明的目标上的方法。(Serhiy Storchaka在 bpo-29209

  • A RuntimeError 当自定义元类不提供 __classcell__ 传递给的命名空间中的项 type.__new__ . 一 DeprecationWarning 在python 3.6--3.7中发出。(Serhiy Storchaka在 bpo-23722

  • 这个 cProfile.Profile 类现在可以用作上下文管理器。(由Scott Sanderson在 bpo-29235

  • shutil.copyfile()shutil.copy()shutil.copy2()shutil.copytree()shutil.move() 使用特定于平台的“快速复制”系统调用(请参见 依赖平台的高效复制操作 部分)。

  • shutil.copyfile() Windows上的默认缓冲区大小已从16 kib更改为1 mib。

  • 这个 PyGC_Head 结构已完全更改。所有触及结构成员的代码都应该重写。(见 bpo-33597

  • 这个 PyInterpreterState 结构已移动到“内部”头文件中(具体包括/internal/pycore_pystate.h)。不透明的 PyInterpreterState 仍然作为公共API(和稳定的ABI)的一部分提供。文档表明结构的字段都不是公共的,所以我们希望没有人使用它们。但是,如果您确实依赖这些私有字段中的一个或多个,并且没有其他选择,请打开BPO问题。我们将帮助您进行调整(可能包括向公共API添加访问函数)。(见 bpo-35886

  • 这个 mmap.flush() 方法现在返回 None 在所有平台下成功并引发错误异常。以前,它的行为依赖于平台:成功时返回非零值;在Windows下,错误时返回零值。成功时返回零值;在Unix下出错时引发异常。(由Berker Peksag于年出资) bpo-2122

  • xml.dom.minidomxml.sax 默认情况下,模块不再处理外部实体。(由Christian Heimes在 bpo-17239

  • 从只读中删除密钥 dbm 数据库 (dbm.dumbdbm.gnudbm.ndbm 提高 error (dbm.dumb.errordbm.gnu.errordbm.ndbm.error )而不是 KeyError . (由张翔于 bpo-33106

  • 简化了文本的AST。所有常数将表示为 ast.Constant 实例。实例化旧类 NumStrBytesNameConstantEllipsis 将返回的实例 Constant . (Serhiy Storchaka在 bpo-32892

  • expanduser() 在Windows上,现在更喜欢 USERPROFILE 环境变量且不使用 HOME ,这通常不为常规用户帐户设置。(安东尼·索蒂尔供稿 bpo-36264

  • 例外 asyncio.CancelledError 现在继承自 BaseException 而不是 Exception 不再继承 concurrent.futures.CancelledError . (由Yury Selivanov在 bpo-32528

  • 函数 asyncio.wait_for() 现在正确地等待在使用 asyncio.Task . 之前,到达时 超时 ,它被取消并立即返回。(埃尔维斯·普兰斯克维丘斯在 bpo-32751

  • 函数 asyncio.BaseTransport.get_extra_info() 现在,当“socket”传递给 name 参数。(Yury Selivanov在 bpo-37027

  • asyncio.BufferedProtocol 已经升级到稳定的API。

  • 用于加载扩展模块和DLL的dll依赖项 ctypes 现在,在Windows上的解决方案更加安全。只有系统路径、包含dll或pyd文件的目录以及添加了 add_dll_directory() 搜索加载时间依赖项。明确地, PATH 当前的工作目录不再使用,对这些目录的修改将不再对正常的DLL解析产生任何影响。如果您的应用程序依赖于这些机制,您应该检查 add_dll_directory() 如果它存在,则在加载库时使用它添加dll目录。请注意,Windows 7用户需要确保已安装Windows Update KB2533623(安装程序也会验证这一点)。(史蒂夫道尔供稿 bpo-36085

  • 与pgen相关的头文件和函数在被纯Python实现替换后被删除。(Pablo Galindo在 bpo-36623

  • types.CodeType 在构造函数的第二个位置有一个新参数( POSONLYARG计数 )支持中定义的仅位置参数的步骤 PEP 570 . 第一个论点( 阿格伯特 )现在表示位置参数(包括仅位置参数)的总数。新的 replace() 方法 types.CodeType 可以用来证明代码的未来。

C API中的更改

  • 这个 PyCompilerFlags 结构有了新的 cf_feature_version 字段。它应该初始化为 PY_MINOR_VERSION . 默认情况下将忽略该字段,并且仅当且仅当 PyCF_ONLY_AST 在中设置了标志 cf_flags . (作者:Guido van Rossum in) bpo-35766

  • 这个 PyEval_ReInitThreads() 函数已从C API中删除。不应显式调用它:使用 PyOS_AfterFork_Child() 相反。(由Victor Stinner在 bpo-36728

  • 在Unix上,除了Android和Cygwin外,C扩展不再链接到libpython。当嵌入python时, libpython 不得加载 RTLD_LOCAL ,但是 RTLD_GLOBAL 相反。以前,使用 RTLD_LOCAL ,已无法加载未链接到的C扩展 libpython 就像标准库的C扩展 *shared* 截面 Modules/Setup . (由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() . 这使得通过 PyType_FromSpec() 行为与托管代码中的其他类类似。

    静态分配的类型不受影响。

    对于绝大多数情况,应该没有副作用。但是,在分配实例后手动增加引用计数的类型(可能是为了解决bug)现在可能成为不朽的。为了避免这种情况,这些类需要在实例释放期间对类型对象调用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);
    

    (由扎克利·斯皮茨在 bpo-33407

  • 解释器不再假装支持跨功能版本的扩展类型的二进制兼容性。一 PyTypeObject 由第三方扩展模块导出的应该具有当前Python版本中预期的所有插槽,包括 tp_finalize (Py_TPFLAGS_HAVE_FINALIZE 阅读前不再检查 tp_finalize

    (由Antoine Pitrou在 bpo-32388

  • 功能 PyNode_AddChild()PyParser_AddToken() 现在接受另外两个 int 参数 end_linenoend_col_offset .

  • 这个 libpython38.a 允许mingw工具直接链接到的文件 python38.dll 不再包含在常规Windows分发中。如果需要此文件,则可以使用 gendefdlltool 工具,属于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 ,通常是 libs python安装下的目录。

    (史蒂夫道尔供稿 bpo-37351

cpython字节码更改

  • 解释器循环通过将块堆栈展开到编译器中的逻辑进行了简化。编译器现在发出明确的指令来调整值的堆栈并调用 breakcontinuereturn .

    删除操作码 BREAK_LOOPCONTINUE_LOOPSETUP_LOOPSETUP_EXCEPT . 添加了新的操作码 ROT_FOURBEGIN_FINALLYCALL_FINALLYPOP_FINALLY . 改变了 END_FINALLYWITH_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

以下是自Python3.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 processor 运行在 python.org . 基准脚本以纳秒为单位显示计时。

Python 3.8.1中的显著变化

由于重大安全问题 reuse_address 参数 asyncio.loop.create_datagram_endpoint() 不再支持。这是因为socket选项的行为 SO_REUSEADDR 在UDP中。有关详细信息,请参阅 loop.create_datagram_endpoint() . (作者:凯尔·斯坦利、安托万·皮特罗和尤里·塞利万诺夫 bpo-37228