Что нового в Python 3.8

Редактор:

Раймонд Хеттингер

В этой статье описываются новые возможности Python 3.8 по сравнению с версией 3.7. Версия Python 3.8 была выпущена 14 октября 2019 года. Более подробную информацию смотрите в 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, которые вычисляют значение для проверки завершения цикла, а затем снова нуждаются в том же значении в теле цикла:

# 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() для функций C, аннотированных с помощью инструмента Ларри Хастингса Argument Clinic.

В следующем примере параметры 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 для получения полного описания.

(Автор: Пабло Галиндо в bpo-36540.)

Кэш параллельной файловой системы для скомпилированных файлов байт-кода

Новый параметр PYTHONPYCACHEPREFIX (также доступен как -X pycache_prefix) настраивает неявный кеш байт-кода для использования отдельного дерева параллельной файловой системы, а не подкаталогов по умолчанию __pycache__ в каждом исходном каталоге.

Местоположение кэша указано в разделе sys.pycache_prefix (None указывает местоположение по умолчанию в подкаталогах __pycache__).

(Автор: Карл Мейер в статье bpo-33499.)

Отладочная сборка использует тот же ABI, что и release build

Python теперь использует один и тот же ABI, независимо от того, собран ли он в режиме выпуска или отладки. В Unix, когда Python собран в режиме отладки, теперь можно загружать расширения C, созданные в режиме выпуска, и расширения C, созданные с использованием стабильного ABI.

Релизные сборки и debug builds теперь совместимы с ABI: определение макроса Py_DEBUG больше не подразумевает использование макроса Py_TRACE_REFS, что приводит к единственной несовместимости с ABI. Макрос Py_TRACE_REFS, который добавляет функцию sys.getobjects() и переменную окружения PYTHONDUMPREFS, можно задать с помощью новой опции построения ./configure --with-trace-refs. (Автор: Виктор Стиннер в bpo-36465.)

В Unix расширения C больше не связаны с libpython, за исключением Android и Cygwin. Теперь статически связанный Python может загружать расширение C, созданное с использованием общей библиотеки Python. (Автор: Виктор Стиннер в bpo-21536.)

В Unix, когда Python собран в режиме отладки, import теперь также ищет расширения C, скомпилированные в режиме выпуска, и расширения C, скомпилированные со стабильным ABI. (Автор: Виктор Стиннер в 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, случаи которых обрабатываются скриптом); это изменение намеренно несовместимо с обратной связью. (Автор: Виктор Стиннер в bpo-36721.)

поддержка f-строк = для самодокументирования выражений и отладки

Добавлен спецификатор = в f-strings. 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 добавлены функции аудита и Verified Open Hook. Оба они доступны как в Python, так и в машинном коде, что позволяет приложениям и фреймворкам, написанным на чистом коде Python, получать дополнительные уведомления, а также позволяет разработчикам внедрений или системным администраторам развертывать сборки Python, в которых всегда включен аудит.

Смотрите PEP 578 для получения более подробной информации.

PEP 587: Конфигурация инициализации Python

PEP 587 добавляет новый C API для настройки инициализации Python, обеспечивая более точный контроль над всей конфигурацией и улучшенную отчетность об ошибках.

Новые структуры:

Новые функции:

Этот PEP также добавляет поля _PyRuntimeState.preconfig (PyPreConfig тип) и PyInterpreterState.config (PyConfig тип) к этим внутренним структурам. PyInterpreterState.config становится новой ссылкой конфигурация, заменяющая глобальные переменные конфигурации и другие частные переменные.

Документацию смотрите в разделе Python Initialization Configuration.

Смотрите PEP 587 для получения полного описания.

(Автор: Виктор Стиннер в bpo-36763.)

PEP 590: Vectorcall: протокол быстрого вызова для CPython

Протокол векторных вызовов добавлен в Python/C API. Он предназначен для формализации существующих оптимизаций, которые уже были выполнены для различных классов. Любой static type, реализующий вызываемый объект, может использовать этот протокол.

В настоящее время это предварительный вариант. Цель состоит в том, чтобы сделать его полностью общедоступным в Python 3.9.

Смотрите PEP 590 для получения полного описания.

(Авторы: Йерун Демейер, Марк Шеннон и Петр Викторин в статье bpo-36974.)

Протокол Pickle 5 с внешними буферами данных

Когда pickle используется для передачи больших объемов данных между процессами Python, чтобы воспользоваться преимуществами многоядерной или многомашинной обработки, важно оптимизировать передачу за счет уменьшения количества копий в памяти и, возможно, применения пользовательских методов, таких как сжатие, зависящее от данных.

Протокол pickle 5 вводит поддержку внеполосных буферов, в которых PEP 3118-совместимые данные могут передаваться отдельно от основного потока pickle, по усмотрению коммуникационного уровня.

Смотрите PEP 574 для получения полного описания.

(Автор: Антуан Питру в статье bpo-36785.)

Другие языковые изменения

  • Утверждение continue было недопустимым в предложении finally из-за проблемы с реализацией. В Python 3.8 это ограничение было снято. (Добавлено Сергеем Сторчакой в bpo-32489.)

  • Типы bool, int, и fractions.Fraction теперь имеют метод as_integer_ratio(), аналогичный тому, который используется в float и decimal.Decimal. Это небольшое расширение API позволяет написать numerator, denominator = x.as_integer_ratio() и заставить его работать с несколькими числовыми типами. (Авторы: Лиза Роуч в bpo-33073 и Раймонд Хеттингер в bpo-37819).

  • Конструкторы int, float и complex теперь будут использовать специальный метод __index__(), если он доступен, а соответствующий метод __int__(), __float__() или __complex__() недоступен. (Автор - Сергей Сторчака в 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
    

    (Материалы предоставлены Джонатаном Юнисом и Сергеем Сторчакой в bpo-30688.)

  • Dick и dictviews не могут быть повторены в обратном порядке вставки, рейтинг reversed(). (Автор: Реми Лапейр в bpo-33462.)

  • Синтаксис, разрешенный для имен ключевых слов в вызовах функций, был дополнительно ограничен. В частности, f((keyword)=arg) больше не допускается. Никогда не предполагалось, что в левой части термина назначения аргумента ключевого слова должно быть что-то большее, чем просто имя. (Автор: Бенджамин Питерсон в статье 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')
    

    (Материалы предоставлены Дэвидом Катбертом и Джорданом Чепменом в bpo-32117.)

  • Когда в коде пропущена запятая, например, [(10, 20) (30, 40)], компилятор отображает SyntaxWarning с полезным предложением. Это улучшает работу с TypeError, указывающим на то, что первый кортеж не был вызван. (Автор - Сергей Сторчака в bpo-15248.)

  • Арифметические операции между подклассами объектов datetime.date или datetime.datetime и datetime.timedelta теперь возвращают экземпляр подкласса, а не базового класса. Это также влияет на возвращаемый тип операций, реализация которых (прямо или косвенно) использует арифметику datetime.timedelta, например, astimezone(). (Добавлено Полом Гансслом в bpo-32417.)

  • Когда интерпретатор Python прерывается нажатием Ctrl-C (SIGINT) и результирующее исключение KeyboardInterrupt не перехватывается, процесс Python завершает работу с помощью сигнала SIGINT или с правильным кодом завершения, чтобы вызывающий процесс мог определить, что он прекратил работу из-за нажатия Ctrl-C. Оболочки в POSIX и Windows используют это для корректного завершения работы скриптов в интерактивных сессиях. (Предоставлено Google через Грегори П. Смита в 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'
    

    (Автор: Виктор Стиннер в 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__(). (Материалы предоставлены Пьером Глейзером и Оливье Гризелем в 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')]
    

    (Авторы: Барри Уоршоу и Джейсон Р. Кумбс в bpo-34632.)

Улучшенные модули

аст

Узлы AST теперь имеют атрибуты end_lineno и end_col_offset, которые указывают точное местоположение конца узла. (Это относится только к узлам, имеющим атрибуты lineno и col_offset.)

Новая функция ast.get_source_segment() возвращает исходный код для определенного узла AST.

(Автор: Иван Левкивский в bpo-33416.)

Функция ast.parse() имеет несколько новых флагов:

  • type_comments=True заставляет его возвращать текст комментариев типа PEP 484 и PEP 526, связанных с определенными узлами AST;

  • mode='func_type' может использоваться для анализа PEP 484 «комментариев типа подписи» (возвращаемых для узлов functiondefinitionAST);

  • feature_version=(3, N) позволяет указать более раннюю версию Python 3. Например, feature_version=(3, 4) будет обрабатывать async и await как незарезервированные слова.

(Автор: Гвидо ван Россум в статье bpo-35766.)

асинхронный

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.

(Автор: Юрий Селиванов в статье 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

(Автор: Юрий Селиванов в статье bpo-37028.)

Исключение asyncio.CancelledError теперь наследуется от BaseException, а не от Exception и больше не наследуется от concurrent.futures.CancelledError. (Добавлено Юрием Селивановым в bpo-32528.)

В Windows цикл обработки событий по умолчанию теперь равен ProactorEventLoop. (Добавлено Виктором Стиннером в bpo-34687.)

ProactorEventLoop теперь также поддерживается UDP. (Добавлено Адамом Мейли и Эндрю Светловым в bpo-29883.)

ProactorEventLoop теперь можно прервать нажатием кнопки KeyboardInterrupt («CTRL+C»). (Добавлено Владимиром Матвеевым в bpo-23057.)

Добавлено asyncio.Task.get_coro() без учета обернутой сопрограммы в asyncio.Task. (Добавлено Алексом Гренхольмом в bpo-36999.)

Задачам Asyncio теперь можно присваивать имена, либо передавая аргумент ключевого слова name в asyncio.create_task(), либо в метод цикла обработки событий create_task(), либо вызывая метод set_name() для объекта task. Название задачи отображается в repr() выходных данных asyncio.Task, а также может быть получено с помощью метода get_name(). (Добавлено Алексом Гренхольмом в bpo-34270.)

Добавлена поддержка Happy Eyeballs в asyncio.loop.create_connection(). Чтобы задать поведение, были добавлены два новых параметра: happy_eyeballs_delay и interleave. Алгоритм Happy Eyeballs улучшает скорость отклика в приложениях, поддерживающих IPv4 и IPv6, за счет одновременного подключения с использованием обоих. (Автор: twisteroid ambassador в bpo-33530).

встроенные модули

Встроенная функция compile() была улучшена, чтобы принимать флаг ast.PyCF_ALLOW_TOP_LEVEL_AWAIT. С переданным этим новым флагом compile() будут разрешены конструкции верхнего уровня await, async for и async with, которые обычно считаются недопустимым синтаксисом. Затем может быть возвращен объект асинхронного кода, помеченный флагом CO_COROUTINE. (Автор - Маттиас Буссонье в статье bpo-34616)

коллекции

Метод _asdict() для collections.namedtuple() теперь возвращает dict вместо collections.OrderedDict. Это работает, потому что обычные диктовки гарантируют упорядочение, начиная с версии Python 3.7. Если требуются дополнительные функции OrderedDict, предлагаемое исправление заключается в приведении результата к желаемому типу: OrderedDict(nt._asdict()). (Материал подготовлен Раймондом Хеттингером в bpo-35864.)

Профайл

Класс cProfile.Profile теперь можно использовать в качестве контекстного менеджера. Создайте профиль блока кода, выполнив:

import cProfile

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

(Автор: Скотт Сандерсон в статье bpo-29235.)

csv-файл

csv.DictReader теперь возвращает значения dict вместо collections.OrderedDict. Инструмент теперь работает быстрее и использует меньше памяти, сохраняя при этом порядок полей. (Автор: Майкл Селик в статье bpo-34003.)

проклятия

Добавлена новая переменная, содержащая структурированную информацию о версии для базовой библиотеки ncurses: ncurses_version. (Добавлено Сергеем Сторчакой в bpo-31680.)

типы данных

В Windows, CDLL и подклассы теперь принимают параметр winmode, чтобы указать флаги для базового вызова LoadLibraryEx. Флаги по умолчанию установлены для загрузки зависимостей DLL только из надежных мест, включая путь, по которому хранится библиотека DLL (если для загрузки исходной библиотеки DLL используется полный или частичный путь), и пути, добавленные с помощью add_dll_directory(). (Автор: Стив Дауэр в статье bpo-36085.)

дата и время

Добавлены новые альтернативные конструкторы datetime.date.fromisocalendar() и datetime.datetime.fromisocalendar(), которые создают объекты date и datetime соответственно из года ISO, номера недели и дня недели; они являются обратными для каждого класса isocalendar способ. (Автор: Пол Ганссл в bpo-36004.)

функциональные средства

functools.lru_cache() теперь можно использовать как обычный декоратор, а не как функцию, возвращающую декоратор. Таким образом, теперь поддерживаются оба этих параметра:

@lru_cache
def f(x):
    ...

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

(Материал подготовлен Раймондом Хеттингером в 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)

(Автор: Карл Мейер в 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() теперь может получать необязательный параметр generation, указывающий поколение, из которого будут получены объекты. (Добавлено Пабло Галиндо в bpo-36016.)

получить текст

Добавлено pgettext() и его варианты. (Авторы: Франц Гласнер, Эрик Араужо и Шерил Сабелла в bpo-2504.)

gzip-файл

Добавлен параметр mtime в gzip.compress() для обеспечения воспроизводимости результатов. ((Добавлено Го Цит Тео в bpo-34898.)

Исключение BadGzipFile Теперь генерируется вместо OSError для определенных типов недействительных или поврежденных файлов gzip. ((Материалы предоставлены Филипом Грущинским, Мишель Орру и Закери Спитцем в bpo-6584.)

ХОЛОСТОЙ ход и idlelib

Вывод в N строках (по умолчанию 50) сокращается до размера кнопки. N можно изменить в разделе PyShell на странице «Общие» диалогового окна настроек. Меньшее количество строк, но, возможно, и более длинных, можно сжать, щелкнув правой кнопкой мыши на выводе. Сжатый вывод можно развернуть на месте, дважды щелкнув по кнопке, или перенести в буфер обмена, или в отдельное окно, щелкнув по кнопке правой кнопкой мыши. (Добавлено Tal Einat в bpo-1529353.)

Добавьте «Запустить настроенный» в меню «Выполнить», чтобы запустить модуль с настроенными настройками. Все введенные аргументы командной строки добавляются в файл sys.argv. Они также отображаются в окне для следующего настроенного запуска. Можно также отключить обычный перезапуск основного модуля оболочки. (Авторы: Шерил Сабелла, Терри Джен Риди и другие в bpo-5680 и bpo-37627.)

Добавлены дополнительные номера строк для неактивных окон редактора. Окна открываются без номеров строк, если не указано иное на вкладке Общие диалогового окна настройки. Номера строк для существующего окна отображаются и скрываются в меню Параметров. (Материалы предоставлены Тал Эйнат и Саймадхавом Хебликаром в bpo-17535.)

Для преобразования строк Python в объекты Tcl теперь используется собственная кодировка операционной системы. Это позволяет IDLE работать с эмодзи и другими символами, отличными от BMP. Эти символы можно отображать или копировать и вставлять в буфер обмена или из него. Преобразование строк из Tcl в Python и обратно теперь никогда не приводит к сбоям. (Многие люди работали над этим в течение восьми лет, но в конце концов проблема была решена Сергеем Сторчакой в bpo-13153.)

Новое в версии 3.8.1:

Добавлена возможность отключить мигание курсора. (Автор: Закери Спитц в bpo-4603.)

Клавиша Escape теперь закрывает незанятые окна завершения. (Добавлено Джонни Наджерой в bpo-38944.)

Приведенные выше изменения были перенесены в версии обслуживания 3.7.

Добавьте ключевые слова в список заполнения названия модуля. (Автор: Терри Дж. Риди в bpo-37765.)

проверить

Функция 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)

(Материал подготовлен Раймондом Хеттингером в bpo-36326.)

ио

В режиме разработки (-X env) и в debug build финализатор io.IOBase теперь регистрирует исключение, если метод close() завершается ошибкой. Исключение по умолчанию автоматически игнорируется при сборке релиза. (Добавлено Виктором Стиннером в bpo-18748.)

итеративные инструменты

Функция itertools.accumulate() добавила аргумент ключевого слова option initial для указания начального значения:

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

(Автор: Лиза Роуч в bpo-34659.)

json.инструмент

Добавьте опцию --json-lines, чтобы анализировать каждую строку ввода как отдельный объект JSON. ((Добавлено Weipeng Hong в bpo-31553.)

регистрация

Добавлен аргумент ключевого слова force в logging.basicConfig() При значении true все существующие обработчики, подключенные к корневому регистратору, удаляются и закрываются перед выполнением конфигурации, указанной в других аргументах.

Это решает давнюю проблему. После вызова логгера или функции basicConfig() последующие вызовы функции basicConfig() автоматически игнорировались. Это затрудняло обновление, экспериментирование или обучение различным параметрам конфигурации ведения журнала с помощью интерактивного приглашения или записной книжки Jupyter.

((Предложено Раймондом Хеттингером, реализовано Донхи На и рассмотрено Винаем Саджипом в bpo-33897.)

математика

Добавлена новая функция math.dist() для вычисления евклидова расстояния между двумя точками. (Добавлено Раймондом Хеттингером в bpo-33089.)

Расширена функция math.hypot() для обработки нескольких измерений. Ранее она поддерживала только двумерный случай. (Добавлено Раймондом Хеттингером в bpo-33089).

Добавлена новая функция, math.prod(), аналогичная функции sum(), которая возвращает произведение начального значения (по умолчанию: 1) на повторяемое число:

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

(Автор: Пабло Галиндо в 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

(Авторы: Яш Аггарвал, Келлер Фукс, Сергей Сторчака и Раймонд Хеттингер в статье 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

(Автор: Марк Дикинсон в bpo-36887.)

Функция math.factorial() больше не принимает аргументы, которые не являются int-подобными. (Добавлено Пабло Галиндо в bpo-33083.)

ммап

В классе mmap.mmap теперь есть метод madvise() для доступа к системному вызову madvise(). (Добавлено Закери Спитцем в bpo-32941.)

многопроцессорная обработка

Добавлен новый модуль multiprocessing.shared_memory. (Автор - Дэвин Поттс в bpo-35813.)

В Mac OS по умолчанию теперь используется метод spawn start. (Автор: Виктор Стиннер в 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.путь

os.path функции, возвращающие логический результат типа exists(), lexists(), isdir(), isfile(), islink(), и ismount() теперь верните False вместо того, чтобы поднимать ValueError или его подклассы UnicodeEncodeError и UnicodeDecodeError для путей, которые содержат символы или байты, непредставимые на уровне операционной системы. (Автор - Сергей Сторчака в bpo-33721.)

expanduser() в Windows теперь используется переменная окружения USERPROFILE и не используется HOME, которая обычно не устанавливается для обычных учетных записей пользователей. (Автор Энтони Соттайл в bpo-36264.)

isdir() в Windows больше не возвращает True для ссылки на несуществующий каталог.

realpath() в Windows теперь разрешаются точки повторного анализа, включая символические ссылки и переходы между каталогами.

(Автор: Стив Дауэр в статье bpo-37834.)

файл пути

pathlib.Path методы, возвращающие логический результат типа exists(), is_dir(), is_file(), is_mount(), is_symlink(), is_block_device(), is_char_device(), is_fifo(), is_socket() теперь возвращают False вместо того, чтобы вызывать ValueError или его подкласс UnicodeEncodeError для путей, содержащих непредставимые символы на уровне операционной системы. (Автор: Сергей Сторчака в bpo-33721.)

Добавлен pathlib.Path.link_to(), который создает жесткую ссылку, указывающую на путь. (Добавлено Джоанной Нанджекай в bpo-26978)

соленый огурец

pickle расширения, подклассифицирующие оптимизированный для C Pickler, теперь могут переопределять логику выбора функций и классов, определяя специальный метод reducer_override(). (Материалы предоставлены Пьером Глейзером и Оливье Гризелем в bpo-35900.)

plistlib - список

Добавлены новые plistlib.UID и включена поддержка чтения и записи двоичных списков plist, закодированных в NSKeyedArchiver. (Автор Джон Янзен в 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'}

(Автор: Реми Лапейр в статье bpo-30670.)

py_compile скомпилировать

py_compile.compile() теперь поддерживается беззвучный режим. (Добавлено Джоанной Нанджекай в bpo-22640.)

шлекс

Новая функция shlex.join() действует как обратная shlex.split(). (Добавлено Бо Бейлсом в bpo-32102.)

выключил

shutil.copytree() теперь принимает новый аргумент ключевого слова dirs_exist_ok. (Добавлено Джошем Бронсоном в bpo-20849.)

shutil.make_archive() теперь по умолчанию используется современный формат pax (POSIX.1-2001) для новых архивов, чтобы улучшить переносимость и соответствие стандартам, унаследованный от соответствующего изменения в модуле tarfile. (Предоставлено К.А.М. Герлахом в bpo-30661.)

shutil.rmtree() в Windows теперь удаляются переходы между каталогами без предварительного рекурсивного удаления их содержимого. (Добавлено Стивом Дауэром в bpo-37834.)

разъем

Добавлены удобные функции create_server() и has_dualstack_ipv6() для автоматизации необходимых задач, обычно выполняемых при создании serversocket, включая прием подключений 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 после подтверждения связи. (Автор Кристиан Хеймс в bpo-34670).

статистика

Добавлен statistics.fmean() как более быстрый вариант statistics.mean() с плавающей запятой. (Авторы - Рэймонд Хеттингер и Стивен Д’Апрано в bpo-35904.)

Добавлено statistics.geometric_mean() (Добавлено Раймондом Хеттингером в bpo-27181.)

Добавлен statistics.multimode(), который возвращает список наиболее распространенных значений. (Добавлено Раймондом Хеттингером в bpo-35892.)

Добавлен statistics.quantiles(), который делит данные или распределение на равновероятные интервалы (например, квартили, децили или процентили). (Добавлено Раймондом Хеттингером в bpo-36546.)

Добавлен statistics.NormalDist, инструмент для создания нормальных распределений случайной величины и управления ими. (Добавлено Раймондом Хеттингером в 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()). (Добавлено Виктором Стиннером в bpo-36829.)

архивный файл

Модуль tarfile теперь по умолчанию использует современный формат pax (POSIX.1-2001) для новых архивов вместо предыдущего формата, специфичного для GNU. Это улучшает межплатформенную переносимость с помощью согласованной кодировки (UTF-8) в стандартизированном и расширяемом формате и дает ряд других преимуществ. (Автор: C.A.M. Герлах в bpo-36268).

нарезание резьбы

Добавьте новую функцию threading.excepthook(), которая обрабатывает неперехваченное исключение threading.Thread.run(). Ее можно переопределить, чтобы управлять обработкой неперехваченных исключений threading.Thread.run(). (Автор: Виктор Стиннер в статье bpo-1230540.)

Добавьте новую функцию threading.get_native_id() и атрибут native_id в класс threading.Thread. Они возвращают собственный интегральный идентификатор текущего потока, назначенный ядром. Эта функция доступна только на определенных платформах, смотрите get_native_id для получения дополнительной информации. (Автор Джейк Теслер в bpo-36084).

обозначить

Модуль tokenize теперь неявно выдает токен NEWLINE при вводе данных, которые не содержат новой строки в конце. Такое поведение теперь соответствует тому, что выполняет внутренний токенизатор C. (Добавлено Аммаром Аскаром в bpo-33899.)

ткинтер

Добавлены методы 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 для mac OS 10.12 (автор Джоанна Нанджекай в bpo-35702).

печатание

Модуль typing включает в себя несколько новых функций:

  • Тип словаря с типами для каждого ключа. Смотрите PEP 589 и typing.TypedDict. В Typedict используются только строковые ключи. По умолчанию требуется наличие каждого ключа. Укажите «total=False», чтобы разрешить использование дополнительных ключей:

    class Location(TypedDict, total=False):
        lat_long: tuple
        grid_square: str
        xy_coordinate: tuple
    
  • Литеральные типы. Смотрите PEP 586 и typing.Literal. Литеральные типы указывают, что параметр или возвращаемое значение ограничено одним или несколькими конкретными литеральными значениями:

    def get_status(port: int) -> Literal['connected', 'disconnected']:
        ...
    
  • «Окончательные» переменные, функции, методы и классы. Смотрите PEP 591, typing.Final и typing.final(). Квалификатор final предписывает программе проверки статических типов ограничить создание подклассов, переопределение или переназначение:

    pi: Final[float] = 3.1415926536
    
  • Определения протоколов. Смотрите PEP 544, typing.Protocol и typing.runtime_checkable(). Простые азбуки, такие как typing.SupportsInt, теперь являются подклассами Protocol.

  • Новый класс протокола typing.SupportsIndex.

  • Новые функции typing.get_origin() и typing.get_args().

данные в юникоде

Модуль unicodedata был обновлен для использования версии Unicode 12.1.0.

Новая функция is_normalized() может быть использована для проверки того, что строка имеет определенную нормальную форму, часто намного быстрее, чем при фактической нормализации строки. (Материалы предоставлены Максом Беленджером, Дэвидом Эврести и Грегом Прайсом в bpo-32285 и bpo-37966).

единичный тест

Добавлен AsyncMock для поддержки асинхронной версии Mock. Также добавлены соответствующие новые функции assert для тестирования. (Добавлено Лизой Роуч в bpo-26467).

Добавлены addModuleCleanup() и addClassCleanup() в модульный тест для поддержки очистки для setUpModule() и setUpClass(). (Добавлено Лизой Роуч в bpo-24412.)

Некоторые фиктивные функции assert теперь также выводят список реальных вызовов в случае сбоя. (Добавлено Петтером Страндмарком в bpo-35047.)

unittest модуль получил поддержку сопрограмм, которые будут использоваться в качестве тестовых примеров с unittest.IsolatedAsyncioTestCase. (Добавлено Андреем Светловым в 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 теперь включает в себя Activate.ps1 скрипт для активации виртуальных сред под управлением PowerShell Core 6.1 на всех платформах (добавлен Бреттом Кэнноном в bpo-32718).

слабая ссылка

Прокси-объекты, возвращаемые weakref.proxy(), теперь поддерживают операторы умножения матриц @ и @= в дополнение к другим числовым операторам. (Добавлено Марком Дикинсоном в bpo-36669.)

xml-код

В качестве защиты от DTD и поиска внешних объектов модули xml.dom.minidom и xml.sax больше не обрабатывают внешние объекты по умолчанию. (Автор Кристиан Хеймс в статье bpo-17239).

Методы .find*() в модуле xml.etree.ElementTree поддерживают поиск по шаблону, например, {*}tag, который игнорирует пространство имен, и {namespace}*, который возвращает все теги в заданном пространстве имен. (Автор: Стефан Бенель в статье bpo-28238.)

Модуль xml.etree.ElementTree предоставляет новую функцию –xml.etree.ElementTree.canonicalize(), которая реализует C14N 2.0. (Добавлена Стефаном Бенелем в bpo-13611).

Целевой объект xml.etree.ElementTree.XMLParser может получать события объявления пространства имен с помощью новых методов обратного вызова start_ns() и end_ns(). Кроме того, целевой объект xml.etree.ElementTree.TreeBuilder может быть сконфигурирован для обработки событий, связанных с комментариями, и инструкций по обработке, чтобы включить их в сгенерированное дерево. (Предоставлено Стефаном Бенелем в bpo-36676 и bpo-36673).

xmlrpc

xmlrpc.client.ServerProxy теперь поддерживается необязательный аргумент ключевого слова headers для последовательности HTTP-заголовков, отправляемых с каждым запросом. Среди прочего, это позволяет перейти от базовой аутентификации по умолчанию к более быстрой аутентификации по сеансу. ((Материал подготовлен Седриком Криером в bpo-35153.)

Оптимизация

  • Модуль subprocess теперь может использовать функцию os.posix_spawn() в некоторых случаях для повышения производительности. В настоящее время он используется только в macOS и Linux (с использованием glibc 2.24 или новее), если соблюдены все эти условия:

    • close_fds имеет значение false;

    • параметры preexec_fn, pass_fds, cwd и start_new_session не заданы;

    • путь к исполняемому файлу содержит каталог.

    (Материалы предоставлены Джоанной Нанджекай и Виктором Стиннером в bpo-35537.)

  • shutil.copyfile(), shutil.copy(), shutil.copy2(), shutil.copytree() и shutil.move() использовать платформо-зависимые «быстрая копия» системные вызовы на Linux и macOS для того, чтобы скопировать файл более эффективно. «быстрое копирование» означает, что операция копирования выполняется внутри ядра, что позволяет избежать использования буферов пользовательского пространства в Python, как в «outfd.write(infd.read())». В Windows shutil.copyfile() используется больший размер буфера по умолчанию (1 МБ вместо 16 КБ), и используется вариант shutil.copyfileobj(), основанный на memoryview(). Ускорение копирования файла размером 512 МБ в пределах одного раздела составляет около +26% в Linux, +50% в macOS и +40% в Windows. Кроме того, значительно сокращается время работы процессора. Смотрите раздел Эффективные операции копирования, зависящие от платформы. (Добавлено Джампаоло Родолой в статье bpo-33671.)

  • shutil.copytree() использует функцию os.scandir(), и все зависящие от нее функции копирования используют кэшированные значения os.stat(). Ускорение копирования каталога с 8000 файлами составляет около +9% в Linux, +20% в Windows и +30% в общем ресурсе Windows SMB. Кроме того, количество системных вызовов os.stat() сокращено на 38%, что делает работу с файловыми системами shutil.copytree() особенно быстрой. (Автор: Джампаоло Родола (Giampaolo Rodolà) в bpo-33695).

  • Протоколом по умолчанию в модуле pickle теперь является протокол 4, впервые представленный в Python 3.4. Он обеспечивает лучшую производительность и меньший размер по сравнению с протоколом 3, доступным начиная с Python 3.0.

  • Удален один элемент Py_ssize_t из PyGC_Head. Размер всех отслеживаемых объектов GC (например, кортежей, списков, dict) уменьшен на 4 или 8 байт. (Автор - Инада Наоки в bpo-33597.)

  • uuid.UUID теперь использует __slots__, чтобы уменьшить объем занимаемой памяти. (Добавлено Воутером Болстерли и Талем Эйнатом в bpo-30977)

  • Улучшена производительность operator.itemgetter() на 33%. Оптимизирована обработка аргументов и добавлен быстрый путь для обычного случая использования одного неотрицательного целого индекса в кортеже (что является типичным случаем использования в стандартной библиотеке). (Материал подготовлен Раймондом Хеттингером в bpo-35664.)

  • Ускоренный поиск по полям в collections.namedtuple(). Теперь они более чем в два раза быстрее, что делает их самой быстрой формой поиска по переменным экземпляра в Python. (Авторы: Рэймонд Хеттингер, Пабло Галиндо и Джо Жевник, Сергей Сторчака в bpo-32492.)

  • Конструктор list не перераспределяет внутренний буфер элементов, если входная итерируемая строка имеет известную длину (вход реализует __len__). В результате созданный список становится в среднем на 12% меньше. (Материалы предоставлены Раймондом Хеттингером и Пабло Галиндо в bpo-33234.)

  • Удвоена скорость записи в переменную класса. При обновлении атрибута, отличного от dunder, возникал ненужный вызов для обновления слотов. (Материалы предоставлены Стефаном Бенелем, Пабло Галиндо Сальгадо, Раймондом Хеттингером, Нилом Шеменауэром и Сергеем Сторчакой в bpo-36012.)

  • Уменьшены затраты на преобразование аргументов, передаваемых многим встроенным функциям и методам. Это ускорило вызов некоторых простых встроенных функций и методов на 20-50%. (Предоставлено Сергеем Сторчакой в bpo-23867, bpo-35582 и bpo-36127.)

  • LOAD_GLOBAL в инструкции теперь используется новый механизм «кэширования для каждого кода операции». Теперь это примерно на 40% быстрее. (Авторы Юрий Селиванов и Инада Наоки в bpo-26219).

Изменения в сборке и C API

  • Значение по умолчанию sys.abiflags стало пустой строкой: флаг m для pymalloc стал бесполезным (сборки с pymalloc и без него совместимы с ABI) и поэтому был удален. (Автор: Виктор Стиннер в 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 должен быть нестабильный C API, специфичный для CPython; общедоступный API с некоторым частным API с префиксом _Py или _PY.

    • Include/internal/*.h это частный внутренний C API, очень специфичный для CPython. Этот API не имеет гарантии обратной совместимости и не должен использоваться за пределами CPython. Он доступен только для очень специфических нужд, таких как отладчики и профилировщики, которым требуется доступ к внутренним компонентам CPython без вызова функций. Этот API теперь установлен make install.

    (Вклад Виктора Стиннера в bpo-35134 и bpo-35081, работа, начатая Эриком Сноу в Python 3.7.)

  • Некоторые макросы были преобразованы в статические встроенные функции: типы параметров и возвращаемый тип четко определены, у них нет проблем, характерных для макросов, переменные имеют локальную область действия. Примеры:

    (Автор: Виктор Стиннер в bpo-35059.)

  • Функции PyByteArray_Init() и PyByteArray_Fini() были удалены. Они ничего не делали со времен Python 2.7.4 и Python 3.2.0, были исключены из ограниченного API (stable API) и не были задокументированы. (Автор: Виктор Стиннер в bpo-35713.)

  • Результат PyExceptionClass_Name() теперь имеет тип const char *, а не char *. (Добавлено Сергеем Сторчакой в bpo-33818.)

  • Двойственность Modules/Setup.dist и Modules/Setup была устранена. Ранее при обновлении дерева исходных текстов CPython приходилось вручную копировать Modules/Setup.dist (внутри дерева исходных текстов) в Modules/Setup (внутри дерева сборки), чтобы отразить любые изменения в вышестоящем потоке. Это принесло небольшую пользу упаковщикам за счет частого раздражения разработчиков после разработки на CPython, поскольку забывание скопировать файл могло привести к сбоям сборки.

    Теперь система сборки всегда выполняет чтение из Modules/Setup в дереве исходного кода. Пользователям, которые хотят настроить этот файл, рекомендуется сохранять свои изменения в git-форке CPython или в виде файлов исправлений, как они делали бы для любых других изменений в дереве исходного кода.

    (Автор: Антуан Питру в статье bpo-32430.)

  • Функции, преобразующие число Python в целое число C, такие как PyLong_AsLong(), и функции анализа аргументов, такие как PyArg_ParseTuple(), с преобразованием единиц формата целых чисел, таких как 'i', теперь будут использовать специальный метод __index__() вместо __int__(), если таковые имеются. Предупреждение об устаревании будет выдаваться для объектов с методом __int__(), но без метода __index__() (например, Decimal и Fraction). PyNumber_Check() теперь будет возвращать 1 для объектов, реализующих __index__(). PyNumber_Long(), PyNumber_Float() и PyFloat_AsDouble() также теперь используйте метод __index__(), если он доступен. (Автор - Сергей Сторчака в bpo-36048 и bpo-20092.)

  • Объекты типа, размещенные в куче, теперь будут увеличивать количество ссылок в PyObject_Init() (и его параллельном макросе PyObject_INIT) вместо PyType_GenericAlloc(). Возможно, потребуется скорректировать типы, которые изменяют распределение или отмену доступа к экземплярам. (Автор Эдди Элизондо в bpo-35810).

  • Новая функция PyCode_NewWithPosOnlyArgs() позволяет создавать объекты кода, подобные PyCode_New(), но с дополнительным параметром posonlyargcount для указания количества позиционных аргументов. (Автор: Пабло Галиндо в статье bpo-37221.)

  • Py_SetPath() теперь присваивает sys.executable полный путь к программе (Py_GetProgramFullPath()), а не имя программы (Py_GetProgramName()). (Автор: Виктор Стиннер в статье bpo-38234.)

Осуждаемый

  • Команда distutils bdist_wininst теперь устарела, вместо нее используйте bdist_wheel (пакеты колес). (Добавлено Виктором Стиннером в bpo-37481.)

  • Устаревшие методы getchildren() и getiterator() в модуле ElementTree теперь выдают DeprecationWarning вместо PendingDeprecationWarning. Они будут удалены в Python 3.9. (Добавлено Сергеем Сторчакой в bpo-29209.)

  • Передача объекта, который не является экземпляром concurrent.futures.ThreadPoolExecutor, в loop.set_default_executor() устарела и будет запрещена в Python 3.9. (Добавлено Элвисом Пранскявичусом в bpo-34075.)

  • Методы __getitem__() из xml.dom.pulldom.DOMEventStream, wsgiref.util.FileWrapper и fileinput.FileInput признаны устаревшими.

    Реализации этих методов игнорировали их параметр index и возвращали вместо него следующий элемент. (Добавлено Беркером Пексагом в bpo-9372.)

  • Класс typing.NamedTuple отменил использование атрибута _field_types в пользу атрибута __annotations__, который содержит ту же информацию. (Добавлено Раймондом Хеттингером в bpo-36320.)

  • ast классы Num, Str, Bytes, NameConstant и Ellipsis считаются устаревшими и будут удалены в будущих версиях Python. вместо этого следует использовать Constant. (Добавлено Сергеем Сторчакой в bpo-32892.)

  • методы ast.NodeVisitor visit_Num(), visit_Str(), visit_Bytes(), visit_NameConstant() и visit_Ellipsis() в настоящее время устарели и не будут вызываться в будущих версиях Python. Добавьте метод visit_Constant() для обработки всех постоянных узлов. (Добавлено Сергеем Сторчакой в bpo-36917.)

  • Параметр asyncio.coroutine() decorator устарел и будет удален в версии 3.10. Вместо @asyncio.coroutine используйте async def. (Автор: Андрей Светлов в статье 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. (Добавлено Юрием Селивановым в bpo-34790.)

  • Следующие функции и методы являются устаревшими в модуле gettext: lgettext(), ldgettext(), lngettext() и ldngettext(). Они возвращают закодированные байты, и возможно, что вы получите неожиданные исключения, связанные с Unicode, если возникнут проблемы с кодировкой переведенных строк. Гораздо лучше использовать альтернативы, которые возвращают строки Unicode в Python 3. Эти функции уже давно не работают.

    Функция bind_textdomain_codeset(), методы output_charset() и set_output_charset(), а также параметр codeset функций translation() и install() также являются устаревшими, поскольку они используются только для l*gettext() функций. (Автор - Сергей Сторчака в bpo-33710.)

  • Метод isAlive() из threading.Thread признан устаревшим. (Добавлено Донхи На в bpo-35283.)

  • Многие встроенные и расширенные функции, принимающие целочисленные аргументы, теперь будут выдавать предупреждение об устаревании для Decimals, Fractions и любых других объектов, которые могут быть преобразованы в целые числа только с потерями (например, которые имеют __int__() метод, но у вас нет метода __index__()). В будущей версии это будут ошибки. (Добавлено Сергеем Сторчакой в bpo-36048.)

  • Рекомендуется передавать следующие аргументы в качестве аргументов ключевых слов:

    В будущих версиях Python они будут positional-only. (Добавлено Сергеем Сторчакой в bpo-36492.)

Удаление API и функций

Следующие функции и API-интерфейсы были удалены из Python 3.8:

  • Начиная с Python 3.3, импорт азбуки из collections устарел, и импорт должен выполняться из collections.abc. Возможность импорта из коллекций была помечена для удаления в версии 3.8, но была отложена до версии 3.9. (см. bpo-36952.)

  • Модуль macpath, считавшийся устаревшим в Python 3.7, был удален. (Автор: Виктор Стиннер в bpo-35471.)

  • Функция platform.popen() была удалена после того, как была признана устаревшей начиная с версии Python 3.3: вместо нее используйте os.popen(). (Автор: Виктор Стиннер в bpo-35345.)

  • Функция time.clock() была удалена после того, как стала устаревшей начиная с версии Python 3.3: используйте вместо нее time.perf_counter() или time.process_time(), в зависимости от ваших требований, для обеспечения четко определенного поведения. (Автор - Маттиас Буссонье в bpo-36895.)

  • Скрипт pyvenv был удален в пользу python3.8 -m venv, чтобы избежать путаницы в отношении того, к какому интерпретатору Python привязан скрипт pyvenv. (Автор Бретт Кэннон в bpo-25427.)

  • parse_qs, parse_qsl, и escape удалены из модуля cgi. В Python версии 3.2 и более ранних версиях они считаются устаревшими. Вместо этого они должны быть импортированы из модулей urllib.parse и html.

  • filemode функция удалена из модуля tarfile. Она не документирована и считается устаревшей начиная с версии Python 3.3.

  • Конструктор XMLParser больше не принимает аргумент html. Это никогда не имело эффекта и было признано устаревшим в Python 3.4. Все остальные параметры теперь равны keyword-only. (Добавлено Сергеем Сторчакой в bpo-29209.)

  • Удален метод doctype() из XMLParser. (Добавлено Сергеем Сторчакой в bpo-29209.)

  • кодек «unicode_internal» удален. (Добавлено Инадой Наоки в bpo-36297.)

  • Объекты Cache и Statement модуля sqlite3 недоступны для пользователя. (Добавлено Авивом Паливодой в bpo-30262.)

  • Аргумент ключевого слова bufsize из fileinput.input() и fileinput.FileInput(), который игнорировался и стал устаревшим с момента выхода Python 3.6, был удален. bpo-36952 (автор - Маттиас Буссонье).

  • Функции sys.set_coroutine_wrapper() и sys.get_coroutine_wrapper(), которые считались устаревшими в Python 3.7, были удалены; bpo-36933 (автор - Маттиас Буссонье).

Перенос на Python 3.8

В этом разделе перечислены ранее описанные изменения и другие исправления ошибок, которые могут потребовать внесения изменений в ваш код.

Изменения в поведении Python

  • Выражения Yield (как yield, так и yield from) теперь запрещены в понятиях и генераторных выражениях (кроме повторяемого выражения в крайнем левом предложении for). (Автор - Сергей Сторчака в bpo-10544.)

  • Компилятор теперь выдает SyntaxWarning, когда проверки подлинности (is и is not) используются с определенными типами литералов (например, строками, числами). В CPython это часто может сработать случайно, но не гарантируется спецификацией языка. В предупреждении рекомендуется вместо этого использовать тесты на равенство (== и !=). (Автор - Сергей Сторчака в bpo-34850.)

  • Интерпретатор Python может пропускать исключения в некоторых случаях. В версии Python 3.8 это происходит в меньшем количестве случаев. В частности, исключения, возникающие при получении атрибута из словаря типов, больше не игнорируются. (Добавлено Сергеем Сторчакой в bpo-35459.)

  • Удалены __str__ реализации из встроенных типов bool, int, float, complex и несколько классов из стандартной библиотеки. Теперь они наследуют __str__() от object. В результате определение метода __repr__() в подклассе этих классов повлияет на их строковое представление. (Автор: Сергей Сторчака в bpo-36793.)

  • В AIX sys.platform больше не содержит основной версии. Это всегда 'aix', вместо 'aix3' .. 'aix7'. Поскольку более старые версии Python содержат номер версии, рекомендуется всегда использовать sys.platform.startswith('aix'). (Добавлено М. Фелтом в bpo-36588.)

  • PyEval_AcquireLock() и PyEval_AcquireThread() теперь завершают текущий поток, если вызываются во время завершения работы интерпретатора, что приводит их в соответствие с PyEval_RestoreThread(), Py_END_ALLOW_THREADS() и PyGILState_Ensure(). Если такое поведение нежелательно, защитите вызов, установив флажок _Py_IsFinalizing() или sys.is_finalizing(). (Добавлено Джоанной Нанджекай в bpo-36475.)

Изменения в Python API

  • Функция os.getcwdb() теперь использует кодировку UTF-8 в Windows, а не кодовую страницу ANSI: смотрите объяснение в PEP 529. Эта функция больше не является устаревшей в Windows. (Автор: Виктор Стиннер в bpo-37412.)

  • subprocess.Popen теперь в некоторых случаях для повышения производительности можно использовать os.posix_spawn(). В подсистеме Windows для Linux и пользовательской эмуляции QEMU конструктор Popen, использующий os.posix_spawn(), больше не вызывает исключения при таких ошибках, как «отсутствует программа». Вместо этого дочерний процесс завершается ошибкой с ненулевым значением returncode. (Материалы предоставлены Джоанной Нанджекай и Виктором Стиннером в bpo-35537.)

  • Аргумент preexec_fn в * subprocess.Popen больше не совместим с вспомогательными интерпретаторами. Использование параметра в подинтерпретаторе теперь вызывает RuntimeError. (Добавлено Эриком Сноу в bpo-34651, изменено Кристианом Хеймсом в bpo-37951.)

  • Метод imap.IMAP4.logout() больше не игнорирует произвольные исключения. (Добавлено Виктором Стиннером в bpo-36348.)

  • Функция platform.popen() была удалена после того, как была признана устаревшей начиная с версии Python 3.3: вместо нее используйте os.popen(). (Автор: Виктор Стиннер в bpo-35345.)

  • Функция statistics.mode() больше не генерирует исключение при вводе мультимодальных данных. Вместо этого она возвращает первый режим, который встречается во входных данных. (Добавлено Раймондом Хеттингером в bpo-35892.)

  • Метод selection() класса tkinter.ttk.Treeview больше не принимает аргументы. Его использование с аргументами для изменения выделения было признано устаревшим в Python 3.6. Для изменения выделения используйте специализированные методы, такие как selection_set(). (Автор - Сергей Сторчака в bpo-31508.)

  • Методы writexml(), toxml() и toprettyxml() из xml.dom.minidom, а также метод write() из xml.etree теперь сохраняют порядок атрибутов, указанный пользователем . (Материалы предоставлены Диего Рохасом и Раймондом Хеттингером в bpo-34160.)

  • База данных dbm.dumb, открытая с флагами 'r', теперь доступна только для чтения. dbm.dumb.open() с флагами 'r' и 'w' больше не создает базу данных, если она не существует. (Автор - Сергей Сторчака в bpo-32749.)

  • Метод doctype(), определенный в подклассе XMLParser, больше не будет вызываться и будет выдавать RuntimeWarning вместо DeprecationWarning. Определите метод doctype() для целевого объекта для обработки объявления типа документа XML. (Добавлено Сергеем Сторчакой в bpo-29209.)

  • Значение RuntimeError теперь возникает, когда пользовательский метакласс не предоставляет запись __classcell__ в пространстве имен, переданном в type.__new__. В Python 3.6-3.7 был создан DeprecationWarning. (Добавлено Сергеем Сторчакой в bpo-23722.)

  • Класс cProfile.Profile теперь можно использовать в качестве контекстного менеджера. (Добавлено Скоттом Сандерсоном в bpo-29235.)

  • shutil.copyfile(), shutil.copy(), shutil.copy2(), shutil.copytree() и shutil.move() использовать системные вызовы «быстрого копирования» для конкретной платформы (см. раздел Эффективные операции копирования, зависящие от платформы).

  • shutil.copyfile() размер буфера по умолчанию в Windows был изменен с 16 КБАЙТ до 1 Мб.

  • Структура PyGC_Head полностью изменилась. Весь код, который касался элемента структуры, должен быть переписан. (см. bpo-33597.)

  • Структура PyInterpreterState была перенесена во «внутренние» заголовочные файлы (в частности, в/internal/pycore_pystate.h). Непрозрачный PyInterpreterState по-прежнему доступен как часть общедоступного API (и стабильного ABI). В документации указано, что ни одно из полей struct не является общедоступным, поэтому мы надеемся, что никто ими не пользовался. Однако, если вы полагаетесь на одно или несколько из этих закрытых полей и у вас нет альтернативы, пожалуйста, откройте проблему с BPO. Мы постараемся помочь вам с настройкой (возможно, включая добавление функций доступа к общедоступному API). (см. bpo-35886).

  • Метод mmap.flush() теперь возвращает None при успешном выполнении и генерирует исключение при ошибке на всех платформах. Ранее его поведение зависело от платформы: при успешном выполнении возвращалось ненулевое значение, при ошибке в Windows - ноль. В случае успешного завершения было возвращено нулевое значение; при ошибке в Unix было вызвано исключение. (Добавлено Беркером Пексагом в bpo-2122.)

  • Модули xml.dom.minidom и xml.sax по умолчанию больше не обрабатывают внешние объекты. (Добавлено Кристианом Хеймсом в bpo-17239.)

  • При удалении ключа из базы данных, доступной только для чтения dbm (dbm.dumb, dbm.gnu или dbm.ndbm), возникает error (dbm.dumb.error, dbm.gnu.error или dbm.ndbm.error) вместо KeyError. (Автор: Сян Чжан в bpo-33106.)

  • Упрощенный AST для литералов. Все константы будут представлены в виде экземпляров ast.Constant. Создание экземпляров старых классов Num, Str, Bytes, NameConstant и Ellipsis вернет экземпляр Constant. (Автор - Сергей Сторчака в bpo-32892.)

  • expanduser() в Windows теперь используется переменная окружения USERPROFILE и не используется HOME, которая обычно не устанавливается для обычных учетных записей пользователей. (Автор Энтони Соттайл в bpo-36264.)

  • Исключение asyncio.CancelledError теперь наследуется от BaseException, а не от Exception и больше не наследуется от concurrent.futures.CancelledError. (Добавлено Юрием Селивановым в bpo-32528.)

  • Функция asyncio.wait_for() теперь корректно ожидает отмены при использовании экземпляра asyncio.Task. Ранее, по достижении таймаута, она отменялась и немедленно возвращалась. (Автор - Элвис Пранскявичус в bpo-32751.)

  • Функция asyncio.BaseTransport.get_extra_info() теперь возвращает безопасный для использования объект socket, когда в параметр name передается „socket“. (Добавлено Юрием Селивановым в bpo-37027.)

  • asyncio.BufferedProtocol перешел на стабильный API.

  • Зависимости DLL для модулей расширения и библиотек DLL, загруженных с помощью ctypes в Windows, теперь разрешены более надежно. Во время загрузки выполняется поиск зависимостей только по системным путям, каталогу, содержащему DLL-файл или PYD-файл, и каталогам, добавленным с помощью add_dll_directory(). В частности, PATH и текущий рабочий каталог больше не используются, и внесенные в них изменения больше не будут влиять на нормальное разрешение библиотек DLL. Если ваше приложение использует эти механизмы, вам следует проверить наличие add_dll_directory() и, если оно существует, использовать его для добавления каталога ваших библиотек DLL при загрузке вашей библиотеки. Обратите внимание, что пользователям Windows 7 необходимо убедиться в том, что установлено обновление Windows KB2533623 (это также проверяется программой установки). (Автор: Стив Дауэр в bpo-36085).

  • Заголовочные файлы и функции, связанные с gene, были удалены после их замены на реализацию на чистом Python. (Автор Пабло Галиндо в bpo-36623).

  • types.CodeType содержит новый параметр во второй позиции конструктора (posonlyargcount) для поддержки только позиционных аргументов, определенных в PEP 570. Первый аргумент (argcount) теперь представляет общее количество позиционных аргументов (включая только позиционные аргументы). Новый метод replace() из types.CodeType может быть использован для повышения надежности кода в будущем.

  • Параметр digestmod для hmac.new() по умолчанию больше не использует дайджест MD5.

Изменения в C API

  • Структура PyCompilerFlags получила новое поле cf_feature_version. Оно должно быть инициализировано значением PY_MINOR_VERSION. По умолчанию это поле игнорируется и используется тогда и только тогда, когда в cf_flags установлен флаг PyCF_ONLY_AST. (Добавлено Гвидо ван Россумом в bpo-35766.)

  • Функция PyEval_ReInitThreads() была удалена из C API. Ее не следует вызывать явно: вместо этого используйте PyOS_AfterFork_Child(). (Автор: Виктор Стиннер в bpo-36728.)

  • В Unix расширения C больше не связаны с libpython, за исключением Android и Cygwin. Когда Python встроен, libpython должен загружаться не с помощью RTLD_LOCAL, а с помощью RTLD_GLOBAL. Ранее, используя RTLD_LOCAL, уже было невозможно загрузить расширения C, которые не были связаны с libpython, например, расширения C стандартной библиотеки, созданные в разделе *shared* раздела Modules/Setup. (Автор: Виктор Стиннер в bpo-21536.)

  • Использование # вариантов форматов при синтаксическом анализе или построении значения (например PyArg_ParseTuple(), Py_BuildValue(), PyObject_CallFunction() и т.д.) без PY_SSIZE_T_CLEAN определено, что сейчас повышается DeprecationWarning. Он будет удален в версии 3.10 или 4.0. Подробнее читайте в статье Анализ аргументов и построение значений. (Добавлено Инадой Наоки в статье bpo-36381.)

  • Экземпляры типов, выделенных в куче (например, созданные с помощью PyType_FromSpec()), содержат ссылку на свой тип object. Увеличение количества ссылок на объекты этого типа было перенесено с PyType_GenericAlloc() на функции более низкого уровня:c:func:PyObject_Init и PyObject_INIT(). Это приводит к тому, что типы, созданные с помощью PyType_FromSpec(), ведут себя как другие классы в управляемом коде.

    Statically allocated types не затрагиваются.

    В подавляющем большинстве случаев побочных эффектов быть не должно. Однако типы, которые вручную увеличивают количество ссылок после выделения экземпляра (возможно, для устранения ошибки), теперь могут стать бессмертными. Чтобы избежать этого, эти классы должны вызывать Py_DECREF для объекта типа во время освобождения экземпляра.

    Чтобы правильно перенести эти типы в версию 3.8, пожалуйста, внесите следующие изменения:

    • Удалите Py_INCREF для объекта type после выделения экземпляра - если таковой имеется. Это может произойти после вызова PyObject_New, PyObject_NewVar, PyObject_GC_New(), PyObject_GC_NewVar() или любого другого пользовательского распределителя, который использует PyObject_Init() или : c:func: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
      }
      

    (Автор: Эдди Элизондо в bpo-35810.)

  • Для MSVC был реализован макрос Py_DEPRECATED(). Теперь макрос должен быть помещен перед именем символа.

    Пример:

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

    (Автор: Закери Спитц в bpo-33407.)

  • Интерпретатор больше не претендует на поддержку бинарной совместимости типов расширений в различных версиях функциональных возможностей. A : c:type:PyTypeObject, экспортированный сторонним модулем расширения, должен содержать все слоты, ожидаемые в текущей версии Python, включая tp_finalize (Py_TPFLAGS_HAVE_FINALIZE больше не проверяется перед чтением tp_finalize).

    (Автор: Антуан Питру в статье bpo-32388.)

  • Функции PyNode_AddChild() и PyParser_AddToken() теперь принимают два дополнительных аргумента int end_lineno и end_col_offset.

  • Файл libpython38.a, позволяющий инструментам MinGW напрямую связываться с python38.dll, больше не входит в обычный дистрибутив Windows. Если вам нужен этот файл, он может быть создан с помощью инструментов gendef и dlltool, которые являются частью пакета MinGW binutils:

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

    Расположение установленного pythonXY.dll будет зависеть от параметров установки, а также от версии и языка Windows. Дополнительную информацию смотрите в разделе Использование Python в Windows. Результирующая библиотека должна быть помещена в тот же каталог, что и pythonXY.lib, который обычно является каталогом libs при установке Python.

    (Автор: Стив Дауэр в статье 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.

    (Авторы: Марк Шеннон, Антуан Питру и Сергей Сторчака в bpo-17611.)

  • Добавлен новый код операции END_ASYNC_FOR для обработки исключений, возникающих при ожидании следующего элемента в цикле async for. (Добавлено Сергеем Сторчакой в bpo-33041.)

  • MAP_ADD теперь ожидает, что значение будет первым элементом в стеке, а ключ - вторым элементом. Это изменение было внесено таким образом, чтобы ключ всегда вычислялся перед значением при чтении по словарю, как предложено в PEP 572. (Добавлено Йорном Хайслером в bpo-35224.)

Демонстрации и инструменты

Добавлен тестовый скрипт для определения времени различных способов доступа к переменным: Tools/scripts/var_access_benchmark.py. (Добавлено Раймондом Хеттингером в 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 processor, на котором были запущены 64-разрядные сборки macOS, найденные по адресу python.org. Тестовый скрипт отображает время в наносекундах.

Заметные изменения в Python 3.8.1

Из-за серьезных проблем с безопасностью параметр reuse_address в asyncio.loop.create_datagram_endpoint() больше не поддерживается. Это связано с поведением параметра сокета SO_REUSEADDR в протоколе UDP. Более подробную информацию смотрите в документации для loop.create_datagram_endpoint(). (Авторы: Кайл Стэнли, Антуан Питру и Юрий Селиванов в bpo-37228.)

Заметные изменения в Python 3.8.2

Исправлена регрессия с обратным вызовом ignore из shutil.copytree(). Теперь типами аргументов снова являются str и List[str]. (Добавлено Мануэлем Бархау и Джампаоло Родолой в gh-83571.)

Заметные изменения в Python 3.8.3

Постоянные значения будущих флагов в модуле __future__ обновлены, чтобы предотвратить столкновение с флагами компилятора. Ранее PyCF_ALLOW_TOP_LEVEL_AWAIT конфликтовал с CO_FUTURE_DIVISION. (Автор: Батухан Таскайя в gh-83743)

Заметные изменения в Python 3.8.8

Более ранние версии Python позволяли использовать как ;, так и & в качестве разделителей параметров запроса в urllib.parse.parse_qs() и urllib.parse.parse_qsl(). Из соображений безопасности и в соответствии с новыми рекомендациями W3C это было изменено, чтобы разрешить использование только одного разделительного ключа с & по умолчанию. Это изменение также затрагивает cgi.parse() и cgi.parse_multipart(), поскольку они используют затронутые функции внутри системы. Для получения более подробной информации, пожалуйста, ознакомьтесь с соответствующей документацией. (Материалы предоставлены Адамом Гольдшмидтом, Сентилом Кумараном и Кеном Джином в bpo-42967.)

Заметные изменения в Python 3.8.9

Исправление безопасности изменяет поведение ftplib.FTP, чтобы не доверять IPv4-адресу, отправляемому с удаленного сервера, при настройке пассивного канала передачи данных. Вместо этого мы используем IP-адрес ftp-сервера. Для необычного кода, требующего старого поведения, установите для атрибута trust_server_pasv_ipv4_address в вашем экземпляре FTP значение 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, продолжайте ориентироваться на самую старую версию в линейке и основываться на ней.

((Первоначально материал был подготовлен Рональдом Оуссореном и Лоуренсом Д’Анной в gh-85272, с исправлениями от FX Coudert и Eli Rykoff, а затем перенесен в версию 3.8 Максимом Беланже и Недом Дейли)

Заметные изменения в Python 3.8.10

urllib.синтаксический анализ

Наличие символов новой строки или табуляции в некоторых частях URL-адреса допускает некоторые формы атак. В соответствии со спецификацией WHATWG, которая обновляет RFC 3986, символы новой строки ASCII \n, \r и табуляции \t удаляются из URL-адреса синтаксическим анализатором в urllib.parse для предотвращения подобных атак. Удаляемые символы управляются новой переменной уровня модуля urllib.parse._UNSAFE_URL_BYTES_TO_REMOVE. (Смотрите bpo-43882)

Заметные изменения в Python 3.8.12

Изменения в Python API

Начиная с версии Python 3.8.12, модуль ipaddress больше не принимает начальные нули в строках адресов IPv4. Начальные нули неоднозначны и интерпретируются некоторыми библиотеками как восьмеричная запись. Например, устаревшая функция socket.inet_aton() обрабатывает начальные нули как восьмеричную запись. реализация glibc в современной inet_pton() не принимает никаких начальных нулей.

(Первоначально добавлено Кристианом Хеймсом в bpo-36384, а затем перенесено в версию 3.8 Ахрафом Мерзуки.)

Примечательная функция безопасности в версии 3.8.14

Преобразование между int и str в основаниях, отличных от 2 (двоичных), 4, 8 (восьмеричных), 16 (шестнадцатеричных) или 32, таких как основание 10 (десятичных), теперь приводит к появлению ValueError, если число количество цифр в виде строки превышает допустимый предел, чтобы избежать потенциальных атак типа «отказ в обслуживании» из-за сложности алгоритма. Это ограничение для CVE-2020-10735. Это ограничение можно настроить или отключить с помощью переменной среды, флага командной строки или sys API. Смотрите документацию по integer string conversion length limitation. Ограничение по умолчанию составляет 4300 цифр в виде строки.

Заметные изменения в версии 3.8.17

архивный файл

  • Методы извлечения в tarfile и shutil.unpack_archive() имеют новый аргумент a filter, который позволяет ограничить возможности tar, которые могут быть неожиданными или опасными, например, создание файлов за пределами каталога назначения. Подробнее смотрите в Экстракционные фильтры. В Python 3.12 при использовании без аргумента filter будет отображаться DeprecationWarning. В Python 3.14 значение по умолчанию будет изменено на 'data'. (Автор: Петр Викторин в PEP 706.)

Вернуться на верх