2025, Nov 21 21:00

Hot-Reload Your Python Packages in Jupyter with importlib: Keep from module import Convenience

Hot-reload Python code in Jupyter with importlib: keep from module import convenience, avoid kernel restarts, and see changes instantly in your notebook.

Hot-reloading your own Python packages in Jupyter can be frustrating when edits don’t show up without a kernel restart. Copying functions into notebook cells is noisy and fragile, while restarting the environment is expensive if you work with large data and heavy imports. The well-known autoreload magic helps, but only when you import modules directly. If you prefer importing functions from a module, you need a simple workflow that keeps your function calls short and still reflects code changes immediately.

Problem statement

In Jupyter, enabling automatic reload looks like this:

%reload_ext autoreload
%autoreload 2

This approach resolves updates for directly imported modules. However, when you import functions from a module instead of importing the module itself, changes are not taken over by default. The goal is to keep the ergonomic from module import func style and still see edits without a full kernel restart.

What’s going on

The core issue is that edits in your local packages aren’t reflected in already imported objects during a live session. Autoreload fixes that for modules brought into the notebook directly, but it doesn’t align with a workflow where functions are imported for convenient naming. The outcome is a mismatch between your edited code on disk and what the notebook actually runs.

Solution with importlib

You can keep using explicitly imported functions while ensuring they stay current by reloading the parent modules via importlib. Importing the parent alongside function-level imports and reloading that parent keeps your function calls short and up to date.

import importlib
import pkg_alpha
import util_box
from util_box import compute_x, compute_y
def hot_reload():
    importlib.reload(pkg_alpha)
    importlib.reload(util_box)

Use it in later cells whenever you change code in your packages:

hot_reload()
compute_x()
compute_y()

Why this matters

This approach preserves the fast iteration loop notebooks are great at. You avoid repeated kernel restarts and keep your datasets and other slow-to-load dependencies in memory. At the same time, you don’t have to sacrifice concise, readable function calls in your cells.

Practical takeaways

Keep a small reload helper in your notebook and call it right before running code that depends on recently edited modules. This gives you a clean, repeatable pattern for interactive development without cluttering cells or restarting the environment.

In short, reloading the parent module with importlib lets you keep your preferred import style, see changes immediately, and maintain a smooth workflow for iterative development in Jupyter.