Що нового в Python 3.8

Редактор:

Raymond Hettinger

У цій статті пояснюється нові функції в Python 3.8 порівняно з 3.7. Python 3.8 було випущено 14 жовтня 2019 року. Щоб отримати повну інформацію, перегляньте журнал змін.

Підсумок – основні моменти випуску

Нові можливості

Вирази присвоєння

Існує новий синтаксис :=, який призначає значення змінним як частину більшого виразу. Його ласкаво називають «оператором моржа» через його схожість з очима та бивнями моржа <https://en.wikipedia.org/wiki/Walrus#/media/File:Pacific_Walrus_-_Bull_(8247646168).jpg>.

У цьому прикладі вираз присвоєння допомагає уникнути виклику 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.)

Лише позиційні параметри

There is a new function parameter syntax / to indicate that some function parameters must be specified positionally and cannot be used as keyword arguments. This is the same notation shown by help() for C functions annotated with Larry Hastings“ Argument Clinic tool.

У наступному прикладі параметри 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

Додаткова перевага позначення параметра як лише позиційного полягає в тому, що це дозволяє змінювати ім’я параметра в майбутньому без ризику зламати код клієнта. Наприклад, у модулі statistic назва параметра dist може бути змінена в майбутньому. Це стало можливим завдяки наступній специфікації функції:

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

Оскільки параметри ліворуч від / не представлені як можливі ключові слова, назви параметрів залишаються доступними для використання в **kwargs:

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

Це значно спрощує реалізацію функцій і методів, які повинні приймати довільні аргументи ключового слова. Наприклад, ось фрагмент коду в модулі collections:

class Counter(dict):

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

Дивіться PEP 570 для повного опису.

(Надав Pablo Galindo в bpo-36540.)

Паралельний кеш файлової системи для скомпільованих файлів байт-коду

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

Розташування кешу повідомляється в sys.pycache_prefix (None вказує на розташування за умовчанням у підкаталогах __pycache__).

(Надано Карлом Майєром у bpo-33499.)

Збірка налагодження використовує той самий ABI, що й збірка випуску

Тепер Python використовує той самий ABI, незалежно від того, чи створено його в режимі випуску чи налагодження. У Unix, коли Python створено в режимі налагодження, тепер можна завантажувати розширення C, створені в режимі випуску, і розширення C, створені за допомогою стабільного ABI.

Випускні збірки та налагоджувальні збірки тепер сумісні з 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 дозволяють краще контролювати відображення результату виразу:

>>> 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 додає Audit Hook і 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 для документації.

Дивіться PEP 587 для повного опису.

(Надав Віктор Стіннер у bpo-36763.)

PEP 590: Vectorcall: швидкий протокол виклику для CPython

Протокол Vectorcall додано до API Python/C. Він призначений для формалізації існуючих оптимізацій, які вже були зроблені для різних класів. Будь-який 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 дає змогу написати чисельник, знаменник = x.as_integer_ratio() і налаштувати його роботу з кількома числовими типами. (Надано Лізою Роуч у bpo-33073 та Реймондом Геттінгером у bpo-37819.)

  • Конструктори int, float і complex тепер використовуватимуть спеціальний метод __index__(), якщо він доступний, і відповідний метод __int__(), __float__() або __complex__() недоступні. (Надав Сергій Сторчака у bpo-20092.)

  • Added support of \N{name} escapes in 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, і відповідний ступінь цієї оберненої величини для інших від’ємних показників степеня. Наприклад, щоб обчислити модульний мультиплікативний обернений 38 за модулем 137, напишіть:

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

    Модульні обернені виникають при розв’язуванні «лінійних діофантових рівнянь <https://en.wikipedia.org/wiki/Diophantine_equation>» _. Наприклад, щоб знайти цілочисельні розв’язки для 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 «коментарів типу підпису» (повертається для вузлів 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() має бути кращим способом запуску асинхронних програм.

(Надав Юрій Селіванов у 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.)

Асинхронним завданням тепер можна присвоювати назви, передавши аргумент ключового слова 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 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. Це працює, оскільки звичайні dicts мають гарантоване впорядкування, починаючи з 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.)

дата, час

Added new alternate constructors datetime.date.fromisocalendar() and datetime.datetime.fromisocalendar(), which construct date and datetime objects respectively from ISO year, week number, and weekday; these are the inverse of each class’s isocalendar method. (Contributed by Paul Ganssle in 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(), який перетворює методи на загальні функції за допомогою 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() для відтворюваного виведення. (Надав Guo Ci Teo в 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. Вікна відкриваються без номерів рядків, якщо не встановлено інше на вкладці «Загальні» діалогового вікна налаштування. Номери рядків для існуючого вікна відображаються та ховаються в меню «Параметри». (Надано Тал Ейнат і Саймадхав Геблікар у 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. (Надано Weipeng Hong у bpo-31553.)

лісозаготівля

Added a force keyword argument to logging.basicConfig(). When set to true, any existing handlers attached to the root logger are removed and closed before carrying out the configuration specified by the other arguments.

Це вирішує давню проблему. Після виклику реєстратора або basicConfig() наступні виклики basicConfig() мовчки ігнорувалися. Через це було складно оновлювати, експериментувати з різними параметрами конфігурації журналу або навчати їх за допомогою інтерактивної підказки або блокнота Jupyter.

(Suggested by Raymond Hettinger, implemented by Donghee Na, and reviewed by Vinay Sajip in 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

(Надано Yash Aggarwal, Keller Fuchs, Serhiy Storchaka та Raymond Hettinger у bpo-37128, bpo-37178 та bpo-35431.)

Додано нову функцію math.isqrt() для обчислення точних цілих квадратних коренів без перетворення до числа з плаваючою комою. Нова функція підтримує довільні цілі числа. Це швидше, ніж floor(sqrt(n)), але повільніше, ніж math.sqrt():

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

(Надав Марк Дікінсон у bpo-36887.)

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

mmap

Клас mmap.mmap тепер має метод madvise() для доступу до системного виклику madvise(). (Надав Закері Шпітц у bpo-32941.)

багатопроцесорність

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

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

ос

Додано нову функцію add_dll_directory() у Windows для надання додаткових шляхів пошуку для власних залежностей під час імпорту модулів розширення або завантаження DLL за допомогою ctypes. (Надав Стів Дауер у bpo-36085.)

Було додано нову функцію os.memfd_create() для обгортання системного виклику memfd_create(). (Надано Zackery Spytz і Christian Heimes у bpo-26836.)

У Windows велика частина ручної логіки для обробки точок повторного аналізу (включаючи символічні посилання та з’єднання каталогів) була делегована операційній системі. Зокрема, os.stat() тепер переглядатиме все, що підтримується операційною системою, тоді як os.lstat() відкриватиме лише точки повторного аналізу, які ідентифікуються як «сурогати імен», тоді як інші відкриваються як для os.stat(). У всіх випадках у stat_result.st_mode буде встановлено лише S_IFLNK для символічних посилань, а не для інших типів точок повторного аналізу. Щоб визначити інші типи точок повторного аналізу, перевірте новий атрибут stat_result.st_reparse_tag.

У Windows os.readlink() тепер може читати з’єднання каталогів. Зауважте, що islink() поверне False для з’єднань каталогів, тому код, який спочатку перевіряє islink, продовжуватиме розглядати з’єднання як каталоги, тоді як код, який обробляє помилки з os.readlink() тепер може розглядати перехрестя як посилання.

(Надав Стів Дауер у 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 methods that return a boolean result like exists(), is_dir(), is_file(), is_mount(), is_symlink(), is_block_device(), is_char_device(), is_fifo(), is_socket() now return False instead of raising ValueError or its subclass UnicodeEncodeError for paths that contain characters unrepresentable at the OS level. (Contributed by Serhiy Storchaka in bpo-33721.)

Added pathlib.Path.link_to() which creates a hard link pointing to a path. (Contributed by Joannah Nanjekye in bpo-26978) Note that link_to was deprecated in 3.10 and removed in 3.12 in favor of a hardlink_to method added in 3.10 which matches the semantics of the existing symlink_to method.

маринований огірок

Розширення 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() тепер підтримує тихий режим. (Надано Joannah Nanjekye у bpo-22640.)

шлекс

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

шутил

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

shutil.make_archive() тепер за замовчуванням використовує сучасний формат pax (POSIX.1-2001) для нових архівів для покращення переносимості та відповідності стандартам, успадкованому від відповідних змін у модулі tarfile. (Надано C.A.M. Gerlach у bpo-30661.)

shutil.rmtree() у Windows тепер видаляє з’єднання каталогів без попереднього рекурсивного видалення їх вмісту. (Надав Стів Дауер у bpo-37834.)

гніздо

Added create_server() and has_dualstack_ipv6() convenience functions to automate the necessary tasks usually involved when creating a server socket, including accepting both IPv4 and IPv6 connections on the same socket. (Contributed by Giampaolo Rodolà in bpo-17561.)

The socket.if_nameindex(), socket.if_nametoindex(), and socket.if_indextoname() functions have been implemented on Windows. (Contributed by Zackery Spytz in bpo-37007.)

ssl

Додано post_handshake_auth для ввімкнення та verify_client_post_handshake() для ініціювання автентифікації TLS 1.3 після рукостискання. (Надав Крістіан Хеймс у bpo-34670.)

статистика

Added statistics.fmean() as a faster, floating-point variant of statistics.mean(). (Contributed by Raymond Hettinger and Steven D’Aprano in bpo-35904.)

Added statistics.geometric_mean() (Contributed by Raymond Hettinger in 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.unraisablehook(), яку можна перевизначати, щоб керувати обробкою «виключних ситуацій, які не можна викликати». Він викликається, коли сталася виняткова ситуація, але Python не може її впоратися. Наприклад, коли деструктор викликає виняток або під час збирання сміття (gc.collect()). (Надав Віктор Стіннер у bpo-36829.)

tarfile

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

різьблення

Додайте нову функцію threading.excepthook(), яка обробляє неперехоплені винятки threading.Thread.run(). Його можна змінити, щоб керувати обробкою неперехоплених винятків threading.Thread.run(). (Надав Віктор Стіннер у bpo-1230540.)

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

токенізувати

Модуль tokenize тепер неявно випромінює маркер NEWLINE, якщо надається вхідні дані, які не мають кінцевого нового рядка. Ця поведінка тепер відповідає внутрішнім функціям C tokenizer. (Надав Аммар Аскар у bpo-33899.)

tkinter

Додано методи selection_from(), selection_present(), selection_range() та selection_to() у клас tkinter.Spinbox. (Надано Juliette Monsel у bpo-34829.)

Додано метод moveto() в клас tkinter.Canvas. (Надано Джульєтт Монсел у bpo-23831.)

Клас tkinter.PhotoImage тепер має методи transparency_get() і transparency_set(). (Надав Закері Шпітц у bpo-25451.)

час

Added new clock CLOCK_UPTIME_RAW for macOS 10.12. (Contributed by Joannah Nanjekye in 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(). Остаточний кваліфікатор наказує статичному засобу перевірки типів обмежити створення підкласів, перевизначення чи перепризначення:

    pi: Final[float] = 3.1415926536
    
  • Визначення протоколу. Перегляньте PEP 544, typing.Protocol і typing.runtime_checkable(). Прості азбуки, такі як typing.SupportsInt тепер є підкласами Protocol.

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

  • Нові функції typing.get_origin() і typing.get_args().

unicodedata

The unicodedata module has been upgraded to use the Unicode 12.1.0 release.

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

unittest

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

Added addModuleCleanup() and addClassCleanup() to unittest to support cleanups for setUpModule() and setUpClass(). (Contributed by Lisa Roach in bpo-24412.)

Кілька імітаційних функцій підтвердження тепер також друкують список фактичних викликів у разі невдачі. (Надано Петтером Страндмарком у 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.proxy(), тепер підтримують оператори множення матриці @ і @= на додаток до інших числових операторів. (Надав Марк Дікінсон у bpo-36669.)

xml

Щоб пом’якшити DTD і пошук зовнішніх об’єктів, модулі xml.dom.minidom і xml.sax більше не обробляють зовнішні об’єкти за замовчуванням. (Надав Крістіан Хеймс у bpo-17239.)

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

The xml.etree.ElementTree module provides a new function –xml.etree.ElementTree.canonicalize() that implements C14N 2.0. (Contributed by Stefan Behnel in 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 є помилковим;

    • Параметри preexec_fn, pass_fds, cwd і start_new_session не встановлені;

    • виконуваний шлях містить каталог.

    (Надано Джоанною Нанджекі та Віктором Стіннером у bpo-35537.)

  • shutil.copyfile(), shutil.copy(), shutil.copy2(), shutil.copytree() і shutil.move() використовують спеціальну для платформи «швидку -copy» системні виклики в Linux і macOS для більш ефективного копіювання файлу. «швидке копіювання» означає, що операція копіювання відбувається всередині ядра, уникаючи використання буферів простору користувача в Python, як у «outfd.write(infd.read())». У Windows shutil.copyfile() використовує більший розмір буфера за замовчуванням (1 МіБ замість 16 КіБ) і використовується варіант memoryview() на основі shutil.copyfileobj(). Прискорення копіювання файлу розміром 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() особливо швидшим у мережевих файлових системах. (Надав Джампаоло Родола в 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__, щоб зменшити обсяг пам’яті. (Надано Wouter Bolsterlee і Tal Einat у 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 — це приватний внутрішній API C, специфічний для CPython. Цей API не має гарантії зворотної сумісності, тому його не слід використовувати поза CPython. Він доступний лише для дуже специфічних потреб, таких як налагоджувачі та профілі, які мають доступ до внутрішніх елементів CPython без виклику функцій. Цей API тепер встановлено за допомогою make install.

    (Надано Віктором Стіннером у bpo-35134 та bpo-35081, робота, розпочата Еріком Сноу над Python 3.7.)

  • Деякі макроси було перетворено на статичні вбудовані функції: типи параметрів і тип повернення добре визначені, вони не мають проблем, характерних для макросів, змінні мають локальні області видимості. приклади:

    (Надав Віктор Стіннер у bpo-35059.)

  • The PyByteArray_Init() and PyByteArray_Fini() functions have been removed. They did nothing since Python 2.7.4 and Python 3.2.0, were excluded from the limited API (stable ABI), and were not documented. (Contributed by Victor Stinner in 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.)

  • The new function PyCode_NewWithPosOnlyArgs() allows to create code objects like PyCode_New(), but with an extra posonlyargcount parameter for indicating the number of positional-only arguments. (Contributed by Pablo Galindo in bpo-37221.)

  • Py_SetPath() now sets sys.executable to the program full path (Py_GetProgramFullPath()) rather than to the program name (Py_GetProgramName()). (Contributed by Victor Stinner in 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.)

  • The __getitem__() methods of xml.dom.pulldom.DOMEventStream, wsgiref.util.FileWrapper and fileinput.FileInput have been deprecated.

    Реалізації цих методів ігнорували параметр index і замість нього повертали наступний елемент. (Надано Berker Peksag у 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.)

  • The isAlive() method of threading.Thread has been deprecated. (Contributed by Donghee Na in bpo-35283.)

  • Багато вбудованих функцій і функцій розширення, які приймають цілі аргументи, тепер видаватимуть попередження про застаріленість для Decimals, Fractions та будь-яких інших об’єктів, які можна перетворити лише на цілі числа із втратою (наприклад, які мають метод __int__(), але не мають методу __index__()). У наступній версії вони будуть помилками. (Надав Сергій Сторчака в bpo-36048.)

  • Застаріло передавати такі аргументи як аргументи ключового слова:

    У майбутніх випусках Python вони будуть позиційними лише. (Надав Сергій Сторчака в bpo-36492.)

Видалення API та функцій

З Python 3.8 видалено наступні функції та API:

  • Starting with Python 3.3, importing ABCs from collections was deprecated, and importing should be done from collections.abc. Being able to import from collections was marked for removal in 3.8, but has been delayed to 3.9. (See gh-81134.)

  • Модуль 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. Усі інші параметри тепер лише для ключових слів. (Надав Сергій Сторчака в 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.)

  • Інтерпретатор CPython може ковтати винятки за деяких обставин. У Python 3.8 це відбувається в меншій кількості випадків. Зокрема, винятки, викликані під час отримання атрибута зі словника типів, більше не ігноруються. (Надав Сергій Сторчака в bpo-35459.)

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

  • On AIX, sys.platform doesn’t contain the major version anymore. It is always 'aix', instead of 'aix3' .. 'aix7'. Since older Python versions include the version number, so it is recommended to always use sys.platform.startswith('aix'). (Contributed by M. Felt in bpo-36588.)

  • PyEval_AcquireLock() and PyEval_AcquireThread() now terminate the current thread if called while the interpreter is finalizing, making them consistent with PyEval_RestoreThread(), Py_END_ALLOW_THREADS(), and PyGILState_Ensure(). If this behavior is not desired, guard the call by checking _Py_IsFinalizing() or sys.is_finalizing(). (Contributed by Joannah Nanjekye in bpo-36475.)

Зміни в API Python

  • Функція 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-декларації doctype. (Надав Сергій Сторчака в bpo-29209.)

  • Помилка RuntimeError тепер виникає, коли спеціальний метаклас не надає запис __classcell__ у просторі імен, переданому в type.__new__. DeprecationWarning було видано в Python 3.6–3.7. (Надав Сергій Сторчака в bpo-23722.)

  • Клас cProfile.Profile тепер можна використовувати як контекстний менеджер. (Надав Скотт Сандерсон у bpo-29235.)

  • shutil.copyfile(), shutil.copy(), shutil.copy2(), shutil.copytree() і shutil.move() використовують спеціальну для платформи «швидку -copy» системні виклики (див. розділ Залежні від платформи ефективні операції копіювання).

  • shutil.copyfile() розмір буфера за замовчуванням у Windows змінено з 16 KiB на 1 MiB.

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

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

  • Метод mmap.flush() тепер повертає None у разі успіху та викликає виняток у разі помилки на всіх платформах. Раніше його поведінка залежала від платформи: ненульове значення поверталося в разі успіху; нуль було повернуто через помилку під Windows. У разі успіху було повернуто нульове значення; виняток було викликано помилкою під Unix. (Надано Berker Peksag у bpo-2122.)

  • Модулі xml.dom.minidom і xml.sax більше не обробляють зовнішні сутності за замовчуванням. (Надав Крістіан Хеймс у bpo-17239.)

  • Видалення ключа з доступної лише для читання бази даних dbm (dbm.dumb, dbm.gnu або dbm.ndbm) викликає error (dbm.dumb.error, dbm.gnu.error або dbm.ndbm.error) замість KeyError. (Надав Xiang Zhang у bpo-33106.)

  • Спрощений AST для літералів. Усі константи будуть представлені як екземпляри ast.Constant. Створення екземплярів старих класів Num, Str, Bytes, NameConstant і Ellipsis поверне екземпляр Constant. (Надав Сергій Сторчака в 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, коли „socket“ передається в параметр name. (Надав Юрій Селіванов у 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 за замовчуванням.

Зміни в C API

  • The PyCompilerFlags structure got a new cf_feature_version field. It should be initialized to PY_MINOR_VERSION. The field is ignored by default, and is used if and only if PyCF_ONLY_AST flag is set in cf_flags. (Contributed by Guido van Rossum in bpo-35766.)

  • The PyEval_ReInitThreads() function has been removed from the C API. It should not be called explicitly: use PyOS_AfterFork_Child() instead. (Contributed by Victor Stinner in 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(), поводитися як інші класи в керованому коді.

    Статично виділені типи не впливають.

    У переважній більшості випадків побічних ефектів бути не повинно. Однак типи, які вручну збільшують кількість посилань після виділення екземпляра (можливо, щоб обійти помилку), тепер можуть стати безсмертними. Щоб уникнути цього, ці класи повинні викликати Py_DECREF для об’єкта типу під час звільнення примірника.

    Щоб правильно перенести ці типи в 3.8, застосуйте такі зміни:

    • Remove Py_INCREF on the type object after allocating an instance - if any. This may happen after calling PyObject_New, PyObject_NewVar, PyObject_GC_New(), PyObject_GC_NewVar(), or any other custom allocator that uses PyObject_Init() or 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.)

  • The interpreter does not pretend to support binary compatibility of extension types across feature releases, anymore. A PyTypeObject exported by a third-party extension module is supposed to have all the slots expected in the current Python version, including tp_finalize (Py_TPFLAGS_HAVE_FINALIZE is not checked anymore before reading tp_finalize).

    (Надав Антуан Пітру в bpo-32388.)

  • The functions PyNode_AddChild() and PyParser_AddToken() now accept two additional int arguments end_lineno and 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

The benchmarks were measured on an Intel® Core™ i7-4960HQ processor running the macOS 64-bit builds found at python.org. The benchmark script displays timings in nanoseconds.

Помітні зміни в Python 3.8.1

Через серйозні проблеми безпеки параметр reuse_address asyncio.loop.create_datagram_endpoint() більше не підтримується. Це через поведінку опції сокета SO_REUSEADDR в UDP. Для отримання додаткової інформації див. документацію для loop.create_datagram_endpoint(). (Надано Кайлом Стенлі, Антуаном Пітру та Юрієм Селівановим у bpo-37228.)

Notable changes in Python 3.8.2

Fixed a regression with the ignore callback of shutil.copytree(). The argument types are now str and List[str] again. (Contributed by Manuel Barkhau and Giampaolo Rodola in gh-83571.)

Notable changes in Python 3.8.3

The constant values of future flags in the __future__ module are updated in order to prevent collision with compiler flags. Previously PyCF_ALLOW_TOP_LEVEL_AWAIT was clashing with CO_FUTURE_DIVISION. (Contributed by Batuhan Taskaya in gh-83743)

Помітні зміни в Python 3.8.8

Попередні версії Python дозволяли використовувати як ;, так і & як роздільники параметрів запиту в urllib.parse.parse_qs() і urllib.parse.parse_qsl(). З міркувань безпеки та для відповідності новим рекомендаціям W3C це було змінено, щоб дозволити лише один роздільний ключ із & за замовчуванням. Ця зміна також впливає на cgi.parse() і cgi.parse_multipart(), оскільки вони використовують уражені функції внутрішньо. Щоб дізнатися більше, перегляньте відповідну документацію. (Надано Адамом Ґолдшмідтом, Сентилом Кумараном і Кеном Джином у bpo-42967.)

Notable changes in Python 3.8.9

A security fix alters the ftplib.FTP behavior to not trust the IPv4 address sent from the remote server when setting up a passive data channel. We reuse the ftp server IP address instead. For unusual code requiring the old behavior, set a trust_server_pasv_ipv4_address attribute on your FTP instance to True. (See gh-87451)

Notable changes in Python 3.8.10

macOS 11.0 (Big Sur) and Apple Silicon Mac support

As of 3.8.10, Python now supports building and running on macOS 11 (Big Sur) and on Apple Silicon Macs (based on the ARM64 architecture). A new universal build variant, universal2, is now available to natively support both ARM64 and Intel 64 in one set of executables. Note that support for «weaklinking», building binaries targeted for newer versions of macOS that will also run correctly on older versions by testing at runtime for missing features, is not included in this backport from Python 3.9; to support a range of macOS versions, continue to target for and build on the oldest version in the range.

(Originally contributed by Ronald Oussoren and Lawrence D’Anna in gh-85272, with fixes by FX Coudert and Eli Rykoff, and backported to 3.8 by Maxime Bélanger and Ned Deily)

Notable changes in Python 3.8.10

urllib.parse

The presence of newline or tab characters in parts of a URL allows for some forms of attacks. Following the WHATWG specification that updates RFC 3986, ASCII newline \n, \r and tab \t characters are stripped from the URL by the parser in urllib.parse preventing such attacks. The removal characters are controlled by a new module level variable urllib.parse._UNSAFE_URL_BYTES_TO_REMOVE. (See bpo-43882)

Помітні зміни в Python 3.8.12

Зміни в API Python

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

(Спочатку надано Крістіаном Хеймсом у bpo-36384, а також перенесено до 3.8 Ахрафом Мерзукі.)

Notable security feature in 3.8.14

Converting between int and str in bases other than 2 (binary), 4, 8 (octal), 16 (hexadecimal), or 32 such as base 10 (decimal) now raises a ValueError if the number of digits in string form is above a limit to avoid potential denial of service attacks due to the algorithmic complexity. This is a mitigation for CVE 2020-10735. This limit can be configured or disabled by environment variable, command line flag, or sys APIs. See the integer string conversion length limitation documentation. The default limit is 4300 digits in string form.

Notable changes in 3.8.17

tarfile

  • The extraction methods in tarfile, and shutil.unpack_archive(), have a new a filter argument that allows limiting tar features than may be surprising or dangerous, such as creating files outside the destination directory. See Extraction filters for details. In Python 3.12, use without the filter argument will show a DeprecationWarning. In Python 3.14, the default will switch to 'data'. (Contributed by Petr Viktorin in PEP 706.)