Встроенная магия Jupyter и библиотека importlib
Привет! На связи Мария Жарова, ментор курсов «ML-инженер» и «Дата-сайентист» 👋🏻
Знакомая ситуация: пишете код в .py-файле, импортируете его в ноутбук, находите баг, правите — и ничего не меняется, пока не перезапустишь ядро и не потеряешь все переменные из памяти 😩 Сегодня про то, как это лечится в две строчки.
Разберём сразу два подхода — встроенную магию Jupyter и библиотеку importlib. Оба решают одну задачу: подхватывать изменения в модулях без перезапуска ядра. Но работают они чуть по-разному, поэтому полезно знать оба.
Способ 1: магические команды %load_ext autoreload
Это самый удобный вариант для повседневной работы. В начале ноутбука пишем две строчки:
%load_ext autoreload
%autoreload 2
И всё — теперь при каждом выполнении ячейки Jupyter будет автоматически перечитывать все импортированные модули, если в них что-то поменялось.
Что означают режимы:
➖ %autoreload 0 — выключено;
➖ %autoreload 1 — перезагружаются только модули, импортированные через %aimport;
➖ %autoreload 2 — перезагружаются все импортированные модули (то, что нужно в 99% случаев).
Типичный сценарий использования:
%load_ext autoreload
%autoreload 2
from my_project.features import build_features
from my_project.models import train_model
X = build_features(df) # запустили
# ... идём в features.py, правим build_features ...
X = build_features(df) # уже работает новая версия, ядро живо
Все переменные (df, обученные модели, загруженные датасеты) остаются в памяти. Магия ✨
Способ 2: importlib.reload — когда нужен контроль
autoreload штука удобная, но иногда мешает: например, если модуль тяжёлый и вы не хотите перечитывать его каждый раз, или если работаете вне Jupyter. Для таких случаев есть встроенный модуль importlib:
import importlib
import my_project.features as features
# ... правим features.py ...
importlib.reload(features)
X = features.build_features(df)
Работает надёжно, но есть нюанс — если вы делали from my_project.features import build_features, то после reload старое имя build_features продолжит указывать на старую функцию. Нужно либо переимпортировать явно:
importlib.reload(features)
from my_project.features import build_features # обновили ссылку
…либо изначально импортировать модуль целиком (import features + features.build_features(...)), а не отдельные функции.
Сохраняйте, чтобы не потерять ❤️
Привет! На связи Мария Жарова, ментор курсов «ML-инженер» и «Дата-сайентист» 👋🏻
Знакомая ситуация: пишете код в .py-файле, импортируете его в ноутбук, находите баг, правите — и ничего не меняется, пока не перезапустишь ядро и не потеряешь все переменные из памяти 😩 Сегодня про то, как это лечится в две строчки.
Разберём сразу два подхода — встроенную магию Jupyter и библиотеку importlib. Оба решают одну задачу: подхватывать изменения в модулях без перезапуска ядра. Но работают они чуть по-разному, поэтому полезно знать оба.
Способ 1: магические команды %load_ext autoreload
Это самый удобный вариант для повседневной работы. В начале ноутбука пишем две строчки:
%load_ext autoreload
%autoreload 2
И всё — теперь при каждом выполнении ячейки Jupyter будет автоматически перечитывать все импортированные модули, если в них что-то поменялось.
Что означают режимы:
➖ %autoreload 0 — выключено;
➖ %autoreload 1 — перезагружаются только модули, импортированные через %aimport;
➖ %autoreload 2 — перезагружаются все импортированные модули (то, что нужно в 99% случаев).
Типичный сценарий использования:
%load_ext autoreload
%autoreload 2
from my_project.features import build_features
from my_project.models import train_model
X = build_features(df) # запустили
# ... идём в features.py, правим build_features ...
X = build_features(df) # уже работает новая версия, ядро живо
Все переменные (df, обученные модели, загруженные датасеты) остаются в памяти. Магия ✨
Способ 2: importlib.reload — когда нужен контроль
autoreload штука удобная, но иногда мешает: например, если модуль тяжёлый и вы не хотите перечитывать его каждый раз, или если работаете вне Jupyter. Для таких случаев есть встроенный модуль importlib:
import importlib
import my_project.features as features
# ... правим features.py ...
importlib.reload(features)
X = features.build_features(df)
Работает надёжно, но есть нюанс — если вы делали from my_project.features import build_features, то после reload старое имя build_features продолжит указывать на старую функцию. Нужно либо переимпортировать явно:
importlib.reload(features)
from my_project.features import build_features # обновили ссылку
…либо изначально импортировать модуль целиком (import features + features.build_features(...)), а не отдельные функции.
Итог: что когда что использовать
📌 %autoreload 2 — дефолт для исследовательской работы в ноутбуках, ставим в первую ячейку и забываем;
📌 importlib.reload — когда autoreload конфликтует с чем-то (иногда бывает с C-расширениями, декораторами, dataclass-ами) или когда нужен точечный контроль;
📌 Комбинация — тоже вариант: autoreload 2 для большинства обычных модулей, а %aimport с режимом 1 для тяжёлых, которые дорого перечитывать.
Сохраняйте, чтобы не потерять ❤️