Что нового в 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)")

Аналогичное преимущество возникает при подборе регулярных выражений, когда объекты match нужны дважды: один раз для проверки, произошло ли совпадение, а другой - для извлечения подгруппы:

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

Оператор также полезен в циклах while, которые вычисляют значение для проверки завершения цикла, а затем требуют это же значение снова в теле цикла:

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

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

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

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

Полное описание см. в разделе PEP 572.

(Предоставлено Эмили Морхаус из bpo-35224).

Только позиционные параметры

Существует новый синтаксис параметров функций / для указания того, что некоторые параметры функций должны быть указаны позиционно и не могут быть использованы в качестве аргументов ключевых слов. Это та же нотация, что и help() для функций языка Си, аннотированных с помощью инструмента Ларри Хастингса 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, что и сборка релиза

Теперь 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 собирается в режиме отладки, импорт теперь также ищет расширения 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 добавляет крючок аудита и проверенный открытый крючок. Оба доступны из 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

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

В настоящее время это предварительный вариант. Цель - сделать его полностью общедоступным в 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).

  • Dict и 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 comprehensions были синхронизированы с dict literals так, что ключ вычисляется первым, а значение вторым:

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

Узлы 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 «комментариев типа сигнатуры» (возвращается для AST-узлов определения функции);

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

(Внесено Гвидо ван Россумом из bpo-35766).

asyncio

asyncio.run() перешла из временного в стабильный API. Эта функция может использоваться для выполнения coroutine и возврата результата при автоматическом управлении циклом событий. Например:

import asyncio

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

asyncio.run(main())

Это почти эквивалентно:

import asyncio

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

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

Фактическая реализация значительно сложнее. Таким образом, asyncio.run() должен быть предпочтительным способом запуска программ asyncio.

(Внесено Юрием Селивановым в 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() на объекте задачи. Имя задачи видно в выводе repr() из asyncio.Task и может быть получено с помощью метода get_name(). (Внесено Алексом Грёнхольмом в bpo-34270).

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

builtins

Встроенная функция 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

Класс 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).

ctypes

В 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

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

gettext

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

gzip

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

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

IDLE и idlelib

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

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

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

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

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

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

Клавиша Escape теперь закрывает окна завершения IDLE. (Внесено Джонни Наджерой в 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).

io

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

itertools

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

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

(Предоставлено Лизой Роуч из bpo-34659).

json.tool

Добавьте опцию --json-lines для разбора каждой входной строки как отдельного объекта JSON. (Внесено Вейпенгом Хонгом в 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.mmap теперь имеет метод madvise() для доступа к системному вызову madvise(). (Внесено Закери Спитцем из bpo-32941).

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

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

В macOS метод запуска spawn теперь используется по умолчанию. (Внесено Виктором Стиннером в bpo-33725).

os

Добавлена новая функция 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 или его подклассы UnicodeEncodeError и UnicodeDecodeError для путей, содержащих символы или байты, непредставимые на уровне ОС. (Внесено Сергеем Сторчакой в 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 для путей, содержащих символы, непредставимые на уровне ОС. (Внесено Сергеем Сторчакой в bpo-33721).

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

маринованный огурец

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

plistlib

Добавлена новая plistlib.UID и включена поддержка чтения и записи бинарных списков с кодировкой NSKeyedArchiver. (Внесено Джоном Янзеном в bpo-26707).

pprint

Модуль 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

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

shutil

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() для автоматизации необходимых задач, обычно возникающих при создании серверного сокета, включая прием соединений 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

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

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

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

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

tokenize

Модуль 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. (Внесено Джоанной Нанджекье в bpo-35702).

набор текста

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

  • Тип словаря с первичными ключами. См. PEP 589 и typing.TypedDict. TypedDict использует только строковые ключи. По умолчанию каждый ключ должен присутствовать. Укажите «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(). Простые ABC, такие как typing.SupportsInt, теперь являются подклассами Protocol.

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

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

unicodedata

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

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

unittest

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

Добавлены addModuleCleanup() и addClassCleanup() в unittest для поддержки очистки для 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

venv теперь включает сценарий Activate.ps1 на всех платформах для активации виртуальных сред под PowerShell Core 6.1. (Внесено Бреттом Кэнноном в bpo-32718).

weakref

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

  • shutil.copytree() использует функцию os.scandir(), а все функции копирования, зависящие от нее, используют кэшированные значения os.stat(). Ускорение при копировании каталога с 8000 файлами составляет около +9% в Linux, +20% в Windows и +30% на SMB ресурсе Windows. Кроме того, количество системных вызовов os.stat() уменьшено на 38%, что делает shutil.copytree() особенно быстрым на сетевых файловых системах. (Внесено Джампаоло Родола в 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).

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

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

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

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

  • По умолчанию 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 (стабильного ABI) и не были документированы. (Внесено Виктором Стиннером в 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).

  • Объекты типа Heap-allocated теперь будут увеличивать количество ссылок в 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).

Утративший силу

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

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

  • Начиная с Python 3.3, импорт ABC из 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) теперь запрещены в выражениях понимания и генераторах (за исключением выражения iterable в крайнем левом предложении for). (Внесено Сергеем Сторчакой в bpo-10544).

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

  • Интерпретатор CPython может проглатывать исключения в некоторых обстоятельствах. В 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).

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

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

  • subprocess.Popen теперь может использовать os.posix_spawn() в некоторых случаях для повышения производительности. В Windows Subsystem for Linux и QEMU User Emulation конструктор Popen, использующий os.posix_spawn(), больше не вызывает исключение при ошибках типа «missing program». Вместо этого дочерний процесс завершается с ненулевым значением 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 doctype. (Внесено Сергеем Сторчакой в 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 KiB на 1 MiB.

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

  • Структура PyInterpreterState была перенесена во «внутренние» заголовочные файлы (в частности, Include/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. Ранее, при достижении timeout, она отменялась и немедленно возвращалась. (Внесено Элвисом Пранскевичусом в 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() и, если он существует, использовать его для добавления каталога DLLs при загрузке вашей библиотеки. Обратите внимание, что пользователям Windows 7 необходимо убедиться, что обновление Windows Update KB2533623 было установлено (это также проверяется программой установки). (Внесено Стивом Дауэром из bpo-36085).

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

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

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

Изменения в API языка C

  • Структура 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()), содержат ссылку на свой объект типа. Увеличение количества ссылок на эти объекты типа было перенесено из PyType_GenericAlloc() в более низкоуровневые функции, PyObject_Init() и PyObject_INIT(). Благодаря этому типы, созданные с помощью PyType_FromSpec(), ведут себя как другие классы в управляемом коде.

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

    В подавляющем большинстве случаев никаких побочных эффектов быть не должно. Однако типы, которые вручную увеличили количество ссылок после выделения экземпляра (возможно, чтобы обойти ошибку), теперь могут стать бессмертными. Чтобы избежать этого, такие классы должны вызывать 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
      }
      

    (Внесено Эдди Элизондо из 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).

    (Внесено Антуаном Питру из 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.8

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

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

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

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

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