Источник: Украл с Reddit
Источник: Украл с Reddit

Относительно недавно приняли PEP-810 и началась ТОТАЛЬНАЯ ТРЯСКА, и я ее не понимаю.

PEP-810 - это нововведение, которое добавляет в Python поддержку явных ленивых импортов. Да-да, теперь можно писать:

lazy import jamlib

и модуль jamlib не будет загружен до тех пор, пока ты реально не воспользуешься им в коде. Это может казаться мелочью, но на самом деле - большое изменение для всей экосистемы Python.

Зачем и кому это надо?

Почти все, что написано на python страдает проблемой долгого старта, особенно CLI инструменты. Даже если делаешь some-cli --help это может затянуться, т.к. питон начнет подгружать ВСЕ что объявлено в импортах, даже если --help никак их не трогает. Ленивые импорты решают эту проблему:

  • не обращаешься к somelib - он не грузится

  • не используешь какой-то модуль - он не грузится в sys.modules

  • не используешь функцию - она не грузится в память

  • gc не тратит 100 лет на выгребание всего этого мусора после старта

Получаем:

  • быстрое время старта

  • меньше поедаем памяти

  • не исполняем код из импорта лишний раз

Как это работает?

В python введена новая синтаксическая конструкция lazy <import_action> <module>, например lazy import math или lazy from jamlib import Jam (Так же введен аргумент запуска python -X lazy_imports=all)

При этом:

  • Ленивые импорты работают только на глобальном уровне, в функции и классы их не прокинуть,

  • импортированный объект сначала - это прокси, который при первом обращении делает реальный импорт и заменяет себя настоящим объектом.

Пример:

lazy import jamlib
print("jamlib" in sys.modules)  # False
print(jamlib.__version__)  # Модуль явно вызывается
print("jamlib" in sys.modules)  # True

И выглядит круто и на деле круто, но…

…в коммьюнити(особенно в русскоязычном) началась ТРЯСКА, я не буду тыкать пальцем в конкретных людей/каналы/посты, но я думаю вы видели этот поток возмущения, вот основные претензии:

  • Зачем нам ещё одно ключевое слово?!

Многие в сообществе возмутились, что lazy засоряет синтаксис. Мол, Python и так превращается в свалку ключевых слов ( async, match, теперь ещё lazy...). Было предложение использовать defer import, import(lazy), или вообще ничего не менять и продолжать писать import внутри функции.

Но это смешно, не нужно - не используй. Вот и все.

  • Ошибки теперь будут позже

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

О ужас, это же реально все меняет (нет)! Для такого аргумента у меня один и тот же ответ: пиши тесты и код проверяй перед тем как лить куда-то.

  • Импорты имеют побочные эффекты

Да, импорты могут делать что-то важное при инициализации, но просто не засовывай их в lazy и не будет проблем.

  • Сложность растет

УУУУ СТАЛО СЛОЖНО, это же целое ключевое слово, лишняя магия. Давайте тогда вообще язык не развивать? Про типы вне typing тоже вой стоял, а сейчас хлебом не корми, дай тайпинга насыпать.

Я лично считаю, что PEP-810 - очень аккуратное и мощное улучшение. Оно не навязывается, оно даёт реальную пользу в больших проектах, и оно не ломает обратную совместимость. Да, баги могут стать чуть менее предсказуемыми. Но зато это шаг к более эффективному и современному Python. Главное - не злоупотреблять, а использовать, когда действительно есть польза.

А тряска - ну, Python-сообщество традиционно очень активно и страстно холиварит без повода. Но мне кажется, что PEP-810 останется, и через год все будут писать lazy import так же спокойно, как async def.