Что нового в Python 3.8
Редактор: | Раймонд Хиттингер |
---|
В этой статье объясняются новые функции Python 3.8 по сравнению с 3.7. Для получения полной информации см. журнал изменений.
Python 3.8 был выпущен 14 октября 2019 года.
Резюме — основные моменты релиза
Новые особенности
Выражения присвоения
Появился новый синтаксис :=
, который присваивает значения переменным как
часть более крупного выражения. Его ласково называют «моржовым оператором»
из-за его сходства с глазами и клыками моржа.
В этом примере выражение присваивания помогает избежать двойного вызова
len()
:
if (n := len(a)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
Аналогичное преимущество возникает при сопоставлении регулярных выражений, когда объекты сопоставления необходимы дважды: один раз для проверки наличия совпадения, а другой — для извлечения подгруппы:
discount = 0.0
if (mo := re.search(r'(\d+)% discount', advertisement)):
discount = float(mo.group(1)) / 100.0
Оператор также полезен с циклами while, которые вычисляют значение для проверки завершения цикла, а затем снова нуждаются в том же значении в теле цикла:
# Цикл на блоках фиксированной длины
while (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()
для функций C, аннотированных с помощью инструмента Клиники споров Ларри Гастингса.
В следующем примере параметры a и b являются только позиционными, тогда как c или d могут быть позиционными или ключевыми, а e или f должны быть ключевыми:
def f(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)
Следующее — действительный вызов:
f(10, 20, 30, d=40, e=50, f=60)
Однако это недействительные вызовы:
f(10, b=20, c=30, d=40, e=50, f=60) # b не может быть ключевым аргументом
f(10, 20, 30, 40, 50, f=60) # e должен быть ключевым аргументом
Одним из вариантов использования этой нотации является то, что она позволяет
чистым функциям Python полностью имитировать поведение существующих функций,
закодированных на C. Например, встроенная функция divmod()
не принимает
ключевые аргументы:
def divmod(a, b, /):
"Эмулирует встроенную функцию divmod() "
return (a // b, a % b)
Другой вариант использования — исключить ключевые аргументы, когда имя
параметра бесполезно. Например, у встроенной функции len()
сигнатура
len(obj, /)
. Это исключает неудобные вызовы, такие как:
len(obj='hello') # Ключевой аргумент "obj" ухудшает читаемость
Ещё одно преимущество маркировки параметра как позиционного состоит в том, что
это позволяет изменять имя параметра в будущем без риска нарушения клиентского
кода. Например, в модуле 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 и b используются двумя способами
10 20 {'a': 1, 'b': 2, 'c': 3}
Это значительно упрощает реализацию функций и методов, которым необходимо
принимать произвольные ключевые аргументы. Например, вот отрывок из кода в
модуле collections
:
class Counter(dict):
def __init__(self, iterable=None, /, **kwds):
# Примечание. "iterable" является возможным ключевым аргументом
См. полное описание в PEP 570.
(Предоставлено Пабло Галиндо в 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-строках. Строка 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-строки позволяет больше контролировать отображения результата выражения:
>>> delta = date.today() - member_since
>>> f'{user=!s} {delta.days=:,d}'
'user=eric_idle delta.days=16,075'
Спецификатор =
отобразит все выражение целиком, чтобы можно было показать
вычисления:
>>> print(f'{theta=} {cos(radians(theta))=:.3f}')
theta=30 cos(radians(theta))=0.866
(Предоставлено Эриком в. Смитом и Ларри Гастингсом в bpo-36817.)
PEP 578: Хуки аудита времени выполнения Python
PEP добавляет Хуки аудита и Verified Open Hook. Оба доступны из Python и собственного кода, что позволяет приложениям и фреймворкам, написанным на чистом коде Python, использовать преимущества дополнительных уведомлений, а также позволяет разработчикам внедрения или системным администраторам развертывать сборки Python, где аудит всегда включен.
См. PEP 578 для получения полной информации.
PEP 587: конфигурация инициализации Python
PEP 587 добавляет новый C API для настройки инициализации Python, обеспечивающий более точный контроль над всей конфигурацией и улучшенный отчёт об ошибках.
Новые конструкции:
Новые функции:
PyConfig_Clear()
PyConfig_InitIsolatedConfig()
PyConfig_InitPythonConfig()
PyConfig_Read()
PyConfig_SetArgv()
PyConfig_SetBytesArgv()
PyConfig_SetBytesString()
PyConfig_SetString()
PyPreConfig_InitIsolatedConfig()
PyPreConfig_InitPythonConfig()
PyStatus_Error()
PyStatus_Exception()
PyStatus_Exit()
PyStatus_IsError()
PyStatus_IsExit()
PyStatus_NoMemory()
PyStatus_Ok()
PyWideStringList_Append()
PyWideStringList_Insert()
Py_BytesMain()
Py_ExitStatusException()
Py_InitializeFromConfig()
Py_PreInitialize()
Py_PreInitializeFromArgs()
Py_PreInitializeFromBytesArgs()
Py_RunMain()
Этот PEP также добавляет к этим внутренним структурам поля
_PyRuntimeState.preconfig
(тип PyPreConfig
) и
PyInterpreterState.config
(тип PyConfig
).
PyInterpreterState.config
становится новой эталонной конфигурацией, заменяя
глобальные переменные конфигурации и другие частные переменные.
См. документацию в Конфигурация инициализации Python.
См. полное описание в PEP 587.
(Предоставлено Виктором Стиннером в bpo-36763)
Vectorcall: протокол быстрого вызова для CPython
Протокол «vectorcall» добавлен в API Python/C. Он предназначен для формализации существующих оптимизаций, которые уже были сделаны для различных классов. Любой тип расширения, реализующий вызываемый объект, может использовать этот протокол.
В настоящее время это временно. Цель состоит в том, чтобы сделать его полностью общедоступным в Python 3.9.
См. полное описание PEP 590.
(Предоставлено Джеруном Демейером и Марком Шенноном в bpo-36974.)
Протокол Pickle 5 с внеполосными буферами данных
Когда pickle
используется для передачи больших данных между процессами
Python, чтобы воспользоваться преимуществами многоядерной или многомашинной
обработки, важно оптимизировать передачу, уменьшив количество копий памяти и,
возможно, применив специальные методы, такие как сжатие, зависящее от данных.
Протокол 5 pickle
вводит поддержку внеполосных буферов, где
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}
врегулярные выражения
:>>> 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 sally') ('SIMPSONS', 'homer', 'marge', 'bart', 'lisa', 'sally')
(Предоставлено Дэвидом Катбертом и Джорданом Чепменом в 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
Модульные инверсии возникают в решении линейных Диофантовых уравнений. Например, чтобы найти целочисленные решения для
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, так что сначала вычисляется ключ, а затем значение:
>>> # словарное включение >>> cast = {input('role? '): input('actor? ') for i in range(2)} role? King Arthur actor? Chapman role? Black Knight actor? Cleese >>> # словарный литерал >>> 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
обеспечивает (предварительную) поддержку чтения метаданных из сторонних пакетов. Например, он может извлекать номер версии установленного пакета, список точек входа и многое другое:>>> # Примечание. В следующем примере требуется, чтобы популярный "requires" >>> # пакет был установлен. >>> >>> 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 к стабильному. Функция может
использоваться для выполнения корутину и возврата результата при
автоматическом управлении циклом событий. Например:
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 ambassador в bpo-33530.)
builtins
Встроенная compile()
была улучшена, чтобы принимать флаг
ast.PyCF_ALLOW_TOP_LEVEL_AWAIT
. После передачи этого нового флага
compile()
разрешит конструкции верхнего уровня await
, async for
и
async with
, которые обычно считаются недопустимым синтаксисом. Затем может
быть возвращен асинхронный объект кода, помеченный флагом CO_COROUTINE
.
(Предоставлено Матиасом Бюссонье в bpo-34616)
collections
Метод _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:
# код для профилирования
...
(Предоставлено Скоттом Сандерсоном в bpo-29235.)
csv
csv.DictReader
теперь возвращает экземпляры dict
вместо
collections.OrderedDict
. Инструмент теперь работает быстрее и
использует меньше памяти, сохраняя при этом порядок полей. (Предоставлено
Майклом Селиком в bpo-34003.)
curses
Добавлена новая переменная, содержащая структурированную информацию о версии
для базовой библиотеки ncurses: ncurses_version
. (Предоставлено
Сергеем Сторчакой в bpo-31680.)
ctypes
В Windows CDLL
и подклассы теперь принимают параметр
winmode, чтобы указать флаги для основного вызова LoadLibraryEx
. Флаги по
умолчанию установлены для загрузки зависимостей DLL только из надежных
расположений, включая путь, в котором хранится DLL (если для загрузки исходной
DLL используется полный или частичный путь), и пути, добавленные
add_dll_directory()
. (Предоставлено Стивом Дауэром в bpo-36085.)
datetime
Добавлены новые альтернативные конструкторы
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()
, который
преобразует методы в общие функции (дженерики), используя
одиночную диспетчеризацию:
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.)
Добавлена «Выполнить индивидуально» в меню «Выполнить», чтобы запустить модуль с индивидуальными настройками. Любые введенные аргументы командной строки добавляются в 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
Функция 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
) и в отладочной сборке финализатор
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.)
logging
Добавлен ключевой аргумент force в logging.basicConfig()
. Если задано
значение истина, все существующие обработчики, подключенные к корневому
регистратору, удаляются и закрываются перед выполнением конфигурации, указанной
другими аргументами.
Это решает давнюю проблему. После вызова регистратора или basicConfig() последующие вызовы basicConfig() игнорировались. Это затрудняло обновление, экспериментирование или обучение различным параметрам конфигурации ведения журнала с помощью интерактивной подсказки или записной книжки Jupyter.
(Предложено Реймондом Хиттингером, реализовано Донг-хи На и рассмотрено Винаем Саджипом в bpo-33897.)
math
Добавлена новая функция 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) # Перестановки 10 вещей, взятых по 3 за раз
720
>>> math.comb(10, 3) # Комбинации из 10 вещей, взятых по 3 за раз
120
(Предоставлено Яшем Аггарвалом, Келлер Фукс, Сергеем Сторчакой и Реймондом Хиттингером в bpo-37128, bpo-37178 и bpo-35431.)
Добавлена новая функция math.isqrt()
для вычисления точных целочисленных
квадратных корней без преобразования в числа с плавающей запятой. Новая функция
поддерживает сколь угодно большие целые числа. Он быстрее, чем
floor(sqrt(n))
, но медленнее, чем math.sqrt()
:
>>> r = 650320427
>>> s = r ** 2
>>> isqrt(s - 1) # правильно
650320426
>>> floor(sqrt(s - 1)) # неправильно
650320427
(Предоставлено Марком Дикинсоном в bpo-36887.)
Функция math.factorial()
больше не принимает аргументы, не похожие на
int. (Предоставлено Пабло Галиндо в bpo-33083.)
mmap
Класс mmap.mmap
теперь имеет метод madvise()
для
доступа к системному вызову madvise()
. (Предоставлено Закери Спитцем в
bpo-32941.)
multiprocessing
Добавлен новый модуль 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
Расширения pickle
, являющиеся подклассом оптимизированного для C
Pickler
, теперь могут отменять логику пиклинга функций и
классов, определяя специальный метод reducer_override()
.
(Предоставлено Пьером Глейзером и Оливье Гризелем в bpo-35900.)
plistlib
Добавлен новый plistlib.UID
и включена поддержка чтения и записи
двоичных списков в кодировке NSKeyedArchiver. (Предоставлено Джоном Янзеном в
bpo-26707.)
pprint
Модуль pprint
добавил параметр sort_dicts к нескольким функциям. По
умолчанию эти функции продолжают сортировку словарей перед отрисовкой или
печатью. Однако, если для sort_dicts задано значение ложь, словари сохраняют
порядок вставки ключей. Это может быть полезно для сравнения с входными данными
JSON во время отладки.
Кроме того, есть удобная новая функция pprint.pp()
, которая похожа на
pprint.pprint()
, но для sort_dicts по умолчанию используется значение
False
:
>>> from pprint import pprint, pp
>>> d = dict(source='input.txt', operation='filter', destination='output.txt')
>>> pp(d, width=40) # Первоначальный порядок
{'source': 'input.txt',
'operation': 'filter',
'destination': 'output.txt'}
>>> pprint(d, width=40) # Ключи отсортированы в алфавитном порядке
{'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.)
socket
Добавлены удобные функции create_server()
и
has_dualstack_ipv6()
для автоматизации необходимых задач,
обычно выполняемых при создании сокета сервера, включая прием соединений IPv4 и
IPv6 на одном сокете. (Предоставлено Джампаоло Родола в bpo-17561.)
Функции socket.if_nameindex()
, socket.if_nametoindex()
и
socket.if_indextoname()
были реализованы в Windows. (Предоставлено
Закери Спитцем в bpo-37007.)
ssl
Добавлен post_handshake_auth
для включения и
verify_client_post_handshake()
для инициирования
аутентификации после установления связи TLS 1.3. (Предоставлено Кристианом
Хеймсом в bpo-34670.)
statistics
Добавлен 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) # Вероятность ниже 3 градусов
0.3184678262814532
>>> # Относительная вероятность быть 7 градусов против 10 градусов
>>> temperature_feb.pdf(7) / temperature_feb.pdf(10)
1.2039930378537762
>>> el_niño = NormalDist(4, 2.5)
>>> temperature_feb += el_niño # Добавим к этому климатический эффект
>>> temperature_feb
NormalDist(mu=10.0, sigma=6.830080526611674)
>>> temperature_feb * (9/5) + 32 # Переводим в градусы Фаренгейта
NormalDist(mu=50.0, sigma=12.294144947901014)
>>> temperature_feb.samples(3) # Генерируем случайные выборки
[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
Добавлена новая функция threading.excepthook()
, которая обрабатывает
неперехваченное исключение threading.Thread.run()
. Его можно
переопределить, чтобы управлять обработкой неперехваченных исключений
threading.Thread.run()
. (Предоставлено Виктором Стиннером в
bpo-1230540.)
Добавлена новая функция threading.get_native_id()
и атрибут
native_id
в класс threading.Thread
. Они
возвращают собственный интегральный идентификатор потока текущего потока,
назначенного ядром. Функция доступна только на определенных платформах,
дополнительную информацию см. в 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.)
time
Добавлены новые часы CLOCK_UPTIME_RAW
для macOS 10.12.
(Предоставлено Джоанной Нанджекье в bpo-35702.)
typing
Модуль typing
включает несколько новых функций:
Тип словаря с типами для каждого ключа. См. PEP 589 и
typing.TypedDict
. TypedDict использует только строковые ключи. По умолчанию требуется наличие каждого ключа. Укажите total=False, чтобы ключи были необязательными:class Location(TypedDict, total=False): lat_long: tuple grid_square: str xy_coordinate: tuple
Буквальные типы. См. 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()
. Простые ABC, напримерtyping.SupportsInt
, теперь являются подклассамиProtocol
.Новый класс протокола
typing.SupportsIndex
.Новые функции
typing.get_origin()
иtyping.get_args()
.
unicodedata
Модуль unicodedata
был обновлен для использования версии Юникод 12.1.0.
Новую функцию is_normalized()
можно использовать для
проверки того, что строка находится в определенной нормальной форме, часто
намного быстрее, чем путем фактической нормализации строки. (Предоставлено
Максом Белэнджером, Дэвидом Эурести и Грегом Прайсом в bpo-32285 и
bpo-37966).
unittest
Добавлен AsyncMock
для поддержки асинхронной версии
Mock
. Также были добавлены соответствующие новые
функции assert для тестирования. (Предоставлено Лизой Роуч в bpo-26467).
В unittest добавлены addModuleCleanup()
и
addClassCleanup()
для поддержки очистки для
setUpModule()
и setUpClass()
.
(Предоставлено Лизой Роуч в bpo-24412.)
Некоторые имитирующие функции assert теперь также выводят список фактических вызовов в случае сбоя. (Предоставлено Петтером Страндмарком в bpo-35047.)
Модуль unittest
получил поддержку корутин, которые будут использоваться
в качестве тестовых примеров с unittest.IsolatedAsyncioTestCase
.
(Предоставлено Андреем Светловым в bpo-32972.)
Пример:
import unittest
class TestRequest(unittest.IsolatedAsyncioTestCase):
async def asyncSetUp(self):
self.connection = await AsyncConnection()
async def test_get(self):
response = await self.connection.get("https://example.com")
self.assertEqual(response.status_code, 200)
async def asyncTearDown(self):
await self.connection.close()
if __name__ == "__main__":
unittest.main()
Venv
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 — Ложь;
- Параметры preexec_fn, pass_fds, cwd и start_new_session не заданы;
- путь executable содержит каталог.
(Предоставлено Джоанной Нанджеки и Виктором Стиннером в bpo-35537.)
shutil.copyfile()
,shutil.copy()
,shutil.copy2()
,shutil.copytree()
иshutil.move()
используют системные вызовы быстрого копирования для платформ в Linux и macOS для более эффективного копирования файла. «быстрое копирование» означает, что операция копирования происходит внутри ядра, избегая использования буферов пользовательского пространства в Python, как в «outfd.write(infd.read())
». В Windowsshutil.copyfile()
использует больший размер буфера по умолчанию (1 МиБ вместо 16 КиБ) и вариантshutil.copyfileobj()
на основеmemoryview()
. Ускорение копирования файла размером 512 МБ в одном разделе составляет около +26% в Linux, +50% в macOS и +40% в Windows. Кроме того, потребляется гораздо меньше циклов процессора. См. раздел Операции эффективного копирования, зависящие от платформы. (Предоставлено Джампаоло Родола в bpo-33671.)shutil.copytree()
использует функциюos.scandir()
, и все функции копирования, зависящие от нее, используют кэшированные значенияos.stat()
. Ускорение копирования каталога с 8000 файлами составляет около +9% для Linux, +20% для Windows и +30% для общего ресурса Windows SMB. Также количество системных вызововos.stat()
уменьшено на 38%, что делаетshutil.copytree()
особенно быстрым в сетевых файловых системах. (Предоставлено Джампаоло Родола в 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.)
Изменения в сборке и C API
По умолчанию
sys.abiflags
стал пустой строкой: флагm
для pymalloc стал бесполезным (сборки с pymalloc и без него совместимы с ABI) и поэтому был удален. (Предоставлено Виктором Стиннером в bpo-36707)Пример изменений:
- Установлена только программа
python3.8
, программаpython3.8m
пропала. - Установлен только скрипт
python3.8-config
, скриптpython3.8m-config
пропал. - Флаг
m
был удален из суффикса имён файлов динамической библиотеки: модули расширения в стандартной библиотеке, а также модули, созданные и устанавливаемые сторонними пакетами, например, загруженные из PyPI. В Linux, например, суффикс Python 3.7.cpython-37m-x86_64-linux-gnu.so
превратился в.cpython-38-x86_64-linux-gnu.so
в Python 3.8.
- Установлена только программа
Файлы заголовков были реорганизованы, чтобы лучше разделить различные типы API:
Include/*.h
должен быть переносимым общедоступным стабильным C API.Include/cpython/*.h
должен быть нестабильным C API, специфичным для CPython; общедоступный API с некоторым частным API с префиксом_Py
или_PY
.Include/internal/*.h
— это частный внутренний C API, очень специфичный для CPython. Этот API не имеет гарантии обратной совместимости и не должен использоваться за пределами CPython. Он предоставляется только для очень специфических потребностей, таких как отладчики и профили, которые должны иметь доступ к внутренним компонентам CPython без вызова функций. Этот API теперь установленmake install
.
(Предоставлено Виктором Стиннером в bpo-35134 и bpo-35081, работа инициирована Эриком Сноу в Python 3.7.)
Некоторые макросы были преобразованы в статические встроенные функции: типы параметров и возвращаемый тип четко определены, у них нет проблем, специфичных для макросов, переменные имеют локальную область видимости. Примеры:
Py_INCREF()
,Py_DECREF()
Py_XINCREF()
,Py_XDECREF()
PyObject_INIT()
,PyObject_INIT_VAR()
- Частные функции:
_PyObject_GC_TRACK()
,_PyObject_GC_UNTRACK()
,_Py_Dealloc()
(Предоставлено Виктором Стиннером в 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.)Объекты типа, размещенные в куче, теперь будут увеличивать счетчик ссылок в
PyObject_Init()
(и его параллельном макросеPyObject_INIT
) вместоPyType_GenericAlloc()
. Типы, которые изменяют выделение или освобождение экземпляров, могут нуждаться в корректировке. (Предоставлено Эдди Элизондо в bpo-35810.)Новая функция
PyCode_NewWithPosOnlyArgs()
позволяет создавать объекты кода, такие какPyCode_New()
, но с дополнительным параметром posonlyargcount для указания количества позиционных аргументов. (Предоставлено Пабло Галиндо в bpo-37221.)Py_SetPath()
теперь устанавливаетsys.executable
на полный путь к программе (Py_GetProgramFullPath()
), а не на имя программы (Py_GetProgramName()
). (Предоставлено Виктором Стиннером в bpo-38234)
Устарело
Команда distutils
bdist_wininst
устарела, использовать вместо неёbdist_wheel
(пакеты колес). (Предоставлено Виктором Стиннером в bpo-37481.)Устаревшие методы
getchildren()
иgetiterator()
в модулеElementTree
теперь выдаютDeprecationWarning
вместоPendingDeprecationWarning
. Они будут удалены в Python 3.9. (Предоставлено Сергеем Сторчакой, bpo-29209.)Передача объекта, не являющегося экземпляром
concurrent.futures.ThreadPoolExecutor
, вloop.set_default_executor()
устарела и будет запрещена в Python 3.9. (Предоставлено Элвисом Пранскевичусом в bpo-34075.)Методы
__getitem__()
дляxml.dom.pulldom.DOMEventStream
,wsgiref.util.FileWrapper
иfileinput.FileInput
устарели.Реализации этих методов игнорировали их параметр index и вместо этого возвращали следующий элемент. (Предоставлено Беркером Пексагом в bpo-9372)
Класс
typing.NamedTuple
отказался от атрибута_field_types
в пользу атрибута__annotations__
, который имеет ту же информацию. (Предоставлено Раймондом Хеттингером в bpo-36320)Классы
ast
Num
,Str
,Bytes
,NameConstant
иEllipsis
считаются устаревшими и будут удалены в будущих версиях Python. Вместо этого следует использоватьConstant
. (Предоставлено Сергеем Сторчакой в bpo-32892.)Методы
ast.NodeVisitor
visit_Num()
,visit_Str()
,visit_Bytes()
,visit_NameConstant()
иvisit_Ellipsis()
сейчас устарели и не будут вызываться в будущих версиях Python. Добавлена методvisit_Constant()
для обработки всех постоянных узлов. (Предоставлено Сергеем Сторчакой в bpo-36917.)asyncio.coroutine()
декоратор устарел и будет удалён в версии 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()
. Они возвращают закодированные байты, и возможно, что вы получить неожиданные исключения, связанные с Юникод, если возникнут проблемы с кодированием переведенных строк. Гораздо лучше использовать альтернативы, которые возвращают строки Юникод в Python 3. Эти функции давно не работают.Функция
bind_textdomain_codeset()
, методыoutput_charset()
иset_output_charset()
, а также параметр codeset функцийtranslation()
иinstall()
также устарели, поскольку они используются только для функцийl*gettext()
. (Предоставлено Сергеем Сторчакой в bpo-33710.)Метод
isAlive()
дляthreading.Thread
устарел. (Предоставлено Дон Хи На в bpo-35283.)Многие встроенные функции и функции расширения, принимающие целочисленные аргументы, теперь будут выдавать предупреждение об устаревании для
Decimal
,Fraction
и любых других объектов, которые могут быть преобразованы в целые числа только с потерей (например, у которых есть метод__int__()
, но нет__index__()
метод). В будущей версии они будут ошибками. (Предоставлено Сергеем Сторчакой в bpo-36048.)Устарела передача следующих аргументов в качестве ключевых аргументов:
- func в
functools.partialmethod()
,weakref.finalize()
,profile.Profile.runcall()
,cProfile.Profile.runcall()
,bdb.Bdb.runcall()
,trace.Trace.runfunc()
иcurses.wrapper()
. - function в
unittest.TestCase.addCleanup()
. - fn в методе
submit()
изconcurrent.futures.ThreadPoolExecutor
иconcurrent.futures.ProcessPoolExecutor
. - callback в
contextlib.ExitStack.callback()
,contextlib.AsyncExitStack.callback()
иcontextlib.AsyncExitStack.push_async_callback()
. - c и typeid в методе
create()
изmultiprocessing.managers.Server
иmultiprocessing.managers.SharedMemoryServer
. - obj в
weakref.finalize()
.
В будущих релизах Python они будут только позиционными. (Предоставлено Сергеем Сторчакой в bpo-36492.)
- func в
Удаление 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. Все остальные параметры теперь только ключевые. (Предоставлено Сергеем Сторчакой в 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.) - В AIX
sys.platform
больше не содержит основную версию. Это всегда'aix'
, а не'aix3'
..'aix7'
. Поскольку более старые версии Python включают номер версии, рекомендуется всегда использоватьsys.platform.startswith('aix')
. (Предоставлено М. Фелтом в bpo-36588.) PyEval_AcquireLock()
иPyEval_AcquireThread()
теперь завершают текущий поток, если вызываются во время завершения интерпретатора, что делает их согласованными сPyEval_RestoreThread()
,Py_END_ALLOW_THREADS()
иPyGILState_Ensure()
. Если такое поведение нежелательно, защитите вызов, проверив_Py_IsFinalizing()
илиsys.is_finalizing()
. (Предоставлено Джоанной Нанджекье в bpo-36475.)
Изменения в Python API
Функция
os.getcwdb()
теперь использует кодировку UTF-8 в Windows, а не кодовую страницу ANSI: объяснение см. в PEP 529. Функция больше не является устаревшей в Windows. (Предоставлено Виктором Стиннером в bpo-37412)subprocess.Popen
теперь может использоватьos.posix_spawn()
в некоторых случаях для повышения производительности. В подсистеме Windows для Linux и пользовательской эмуляции QEMU конструкторPopen
, использующийos.posix_spawn()
, больше не вызывает исключения при таких ошибках, как «отсутствует программа». Вместо этого дочерний процесс завершается ошибкой с ненулевымreturncode
. (Предоставлено Джоанной Нанджекье и Виктором Стиннером в bpo-35537.)Аргумент preexec_fn *
subprocess.Popen
больше не совместим с субинтерпретаторами. Использование параметра в субинтерпретаторе теперь вызываетRuntimeError
. (Предоставлено Эриком Сноу в bpo-34651, изменено Кристианом Хеймсом в bpo-37951.)Метод
imap.IMAP4.logout()
больше не игнорирует произвольные исключения. (Предоставлено Виктором Стиннером в bpo-36348.)Функция
platform.popen()
была удалена после того, как она устарела с Python 3.3: вместо нее использоватьos.popen()
. (Предоставлено Виктором Стиннером в bpo-35345)Функция
statistics.mode()
больше не вызывает исключение при передаче мультимодальных данных. Вместо этого он возвращает первый режим, обнаруженный во входных данных. (Предоставлено Раймондом Хеттингером в bpo-35892)Метод
selection()
классаtkinter.ttk.Treeview
больше не принимает аргументы. Использование его с аргументами для изменения выбора было устаревшим в Python 3.6. Использовать специальные методы, такие какselection_set()
, для изменения выделения. (Предоставлено Сергеем Сторчакой, bpo-31508.)Методы
writexml()
,toxml()
иtoprettyxml()
дляxml.dom.minidom
и методwrite()
дляxml.etree
теперь сохраняют порядок атрибутов, указанный пользователем. (Предоставлено Диего Рохасом и Раймондом Хеттингером в bpo-34160)База данных
dbm.dumb
, открытая с флагами'r'
, теперь доступна только для чтения.dbm.dumb.open()
с флагами'r'
и'w'
больше не создает базу данных, если она не существует. (Предоставлено Сергеем Сторчакой, bpo-32749.)Метод
doctype()
, определенный в подклассеXMLParser
, больше не будет вызываться и будет выдаватьRuntimeWarning
вместоDeprecationWarning
. Определите методdoctype()
на целевом объекте для обработки объявления типа XML. (Предоставлено Сергеем Сторчакой в bpo-29209.)Теперь вызывается
RuntimeError
, когда пользовательский метакласс не предоставляет запись__classcell__
в пространстве имен, переданном вtype.__new__
.DeprecationWarning
был выпущен в Python 3.6–3.7. (Предоставлено Сергеем Сторчакой, bpo-23722.)Класс
cProfile.Profile
теперь можно использовать в качестве менеджера контекста. (Предоставлено Скоттом Сандерсоном в bpo-29235.)shutil.copyfile()
,shutil.copy()
,shutil.copy2()
,shutil.copytree()
иshutil.move()
используют системные вызовы быстрого копирования для разных платформ (см. раздел Операции эффективного копирования, зависящие от платформы).Размер буфера по умолчанию
shutil.copyfile()
в Windows изменён с 16 КиБ на 1 МиБ.Структура
PyGC_Head
полностью изменилась. Весь код, касающийся члена структуры, должен быть переписан. (См. bpo-33597.)Структура
PyInterpreterState
перемещена во «внутренние» файлы заголовков (в частности, Include/internal/pycore_pystate.h). НепрозрачныйPyInterpreterState
по-прежнему доступен как часть общедоступного API (и стабильного ABI). В документации указано, что ни одно из полей структуры не является общедоступным, поэтому мы надеемся, что никто их не использовал. Однако, если вы полагаетесь на одно или несколько из этих частных полей и у вас нет альтернативы, пожалуйста, открыть проблему 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()
теперь возвращает безопасный для использования объект сокета, когда «сокет» передается в параметр name. (Предоставлено Юрием Селивановым в bpo-37027.)asyncio.BufferedProtocol
перешёл на стабильный API.
- Зависимости DLL для модулей расширения и DLL, загружаемых с
ctypes
в Windows, теперь разрешаются более безопасно. Только системные пути, каталог, содержащий файл DLL или PYD, и каталоги, добавленные с помощьюadd_dll_directory()
, ищутся на предмет зависимостей во время загрузки. В частности,PATH
и текущий рабочий каталог больше не используются, и их модификации больше не будут влиять на нормальное разрешение DLL. Если ваше приложение использует эти механизмы, вам следует проверить наличиеadd_dll_directory()
и, если он существует, использовать его для добавления каталога DLL при загрузке библиотеки. Обратите внимание, что пользователям Windows 7 необходимо убедиться, что установлен Центр обновления Windows KB2533623 (это также проверяется установщиком). (Предоставлено Стивом Дауэром в bpo-36085.) - Заголовочные файлы и функции, связанные с pgen, были удалены после их замены чистой реализацией Python. (Предоставлено Пабло Галиндо в bpo-36623.)
types.CodeType
имеет новый параметр во второй позиции конструктора (posonlyargcount) для поддержки позиционных аргументов, определенных в PEP 570. Первый аргумент (argcount) теперь представляет общее количество позиционных аргументов (включая только позиционные аргументы). Новый методreplace()
изtypes.CodeType
может использоваться для обеспечения соответствия кода требованиям завтрашнего дня.
Изменения в C API
В структуреPyCompilerFlags
появилось новое поле cf_feature_version. Его следует инициализировать какPY_MINOR_VERSION
. Поле игнорируется по умолчанию и используется тогда и только тогда, когда в cf_flags установлен флагPyCF_ONLY_AST
. (Предоставлено Гвидо ван Россумом в bpo-35766.)
Функция
PyEval_ReInitThreads()
удалена из C API. Его не следует вызывать явно: использовать вместо негоPyOS_AfterFork_Child()
. (Предоставлено Виктором Стиннером в bpo-36728)В Unix расширения C больше не связаны с libpython, за исключением Android и Cygwin. Когда Python встроен,
libpython
должен загружаться не сRTLD_LOCAL
, а сRTLD_GLOBAL
. Ранее при использованииRTLD_LOCAL
уже было невозможно загрузить расширения C, которые не были связаны сlibpython
, например расширения C стандартной библиотеки, созданной разделом*shared*
Modules/Setup
. (Предоставлено Виктором Стиннером в bpo-21536.)Использование вариантов форматов
#
при синтаксическом анализе или построении значения (например,PyArg_ParseTuple()
,Py_BuildValue()
,PyObject_CallFunction()
и т. д.) Без определенияPY_SSIZE_T_CLEAN
вызываетDeprecationWarning
. Он будет удален в 3.10 или 4.0. Подробности читайте в Анализ аргументов и сборка значений. (Предоставлено Инадой Наоки в bpo-36381.)Экземпляры типов с распределением в куче (например, созданные с помощью
PyType_FromSpec()
) содержат ссылку на свой объект типа. Увеличение числа ссылок для объектов этого типа было перемещено изPyType_GenericAlloc()
в функции более низкого уровня,PyObject_Init()
иPyObject_INIT()
. Это заставляет типы, созданные с помощьюPyType_FromSpec()
, вести себя как другие классы в управляемом коде.Статически выделенные типы не затрагиваются.
В подавляющем большинстве случаев побочных эффектов быть не должно. Однако типы, которые вручную увеличивают счётчик ссылок после выделения экземпляра (возможно, чтобы обойти ошибку), теперь могут стать бессмертными. Чтобы этого избежать, этим классам необходимо вызывать Py_DECREF для объекта типа во время освобождения экземпляра.
Чтобы правильно перенести эти типы в 3.8, внесите следующие изменения:
Удалить
Py_INCREF
на объекте типа после выделения экземпляра — если таковой имеется. Это может произойти после вызоваPyObject_New()
,PyObject_NewVar()
,PyObject_GC_New()
,PyObject_GC_NewVar()
или любого другого настраиваемого распределителя, использующегоPyObject_Init()
илиPyObject_INIT()
.Пример:
static foo_struct * foo_new(PyObject *type) { foo_struct *foo = PyObject_GC_New(foo_struct, (PyTypeObject *) type); if (foo == NULL) return NULL; #if PY_VERSION_HEX < 0x03080000 // Обходной путь для проблемы Python 35810; больше не требуется в 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 // Это не было необходимо до Python 3.8 (проблема Python 35810) Py_DECREF(type); #endif }
(Предоставлено Эдди Элизондо в bpo-35810.)
Макрос: c:macro: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 процессоре с 64-разрядными сборками macOS, найденными по адресу python.org. Сценарий тестирования отображает время в наносекундах.
Заметные изменения в Python 3.8.1
Из-за серьезных проблем с безопасностью параметр reuse_address для
asyncio.loop.create_datagram_endpoint()
больше не поддерживается. Это
связано с поведением параметра сокета SO_REUSEADDR
в UDP. Для получения
дополнительных сведений см. документацию для
loop.create_datagram_endpoint()
. (Предоставлено Кайлом Стэнли, Антуаном
Питру и Юрием Селивановым в bpo-37228.)
Заметные изменения в Python 3.8.2
Исправлена регрессия с обратным вызовом ignore
для shutil.copytree()
.
Типы аргументов теперь снова str и List[str]. (Предоставлено Мануэлем Баркхау
и Джампаоло Родола в bpo-39390.)
Заметные изменения в Python 3.8.3
Постоянные значения будущих флагов в модуле __future__
обновляются,
чтобы предотвратить конфликт с флагами компилятора. Ранее
PyCF_ALLOW_TOP_LEVEL_AWAIT
конфликтовал с CO_FUTURE_DIVISION
.
(Предоставлено Батуханом Таская в bpo-39562)
Заметные изменения в Python 3.8.8
Более ранние версии Python позволяли использовать как ;
, так и &
в
качестве разделителей параметров запроса в urllib.parse.parse_qs()
и
urllib.parse.parse_qsl()
. Из соображений безопасности и в соответствии с
новыми рекомендациями W3C это было изменено, чтобы разрешить использование
только одного ключа-разделителя &
по умолчанию. Это изменение также
влияет на cgi.parse()
и cgi.parse_multipart()
, поскольку они
используют затронутые функции внутри. Для получения дополнительных сведений см.
соответствующую документацию. (Предоставлено Адамом Гольдшмидтом, Сентил
Кумаран и Кен Джин в bpo-42967.)