unwrapt
Don’t open it until you need it.
Every import in your program is a present your program unwraps
immediately, whether or not it uses what is inside. unwrapt leaves the
wrapping on until first use: it defers whole-module imports until the
moment they are touched, cutting start-up time, without changing your
application’s code.
Python 3.15 adds lazy imports (PEP 810): a lazy import x statement,
and a module-level __lazy_modules__ list that keeps the imports it
names deferred while remaining ordinary valid code on older Pythons.
unwrapt brings the __lazy_modules__ behaviour to Python 3.12 to 3.14,
emulating it on top of
wrapt so the same source
behaves the same on every version. It is a sibling project to
wrapt and
autowrapt, and with
autowrapt installed one
environment variable activates it, with no application change.
It also ships a profile mode that measures what your imports actually cost on a real run and reports what is worth deferring, on any Python version including 3.15.
Note
unwrapt is in alpha ahead of 1.0.0, with pre-releases published to
PyPI. Until 1.0.0 is final, a
plain pip install unwrapt picks up the latest pre-release
automatically, so there is no need to pin a specific version. Small
API changes are still possible before 1.0.0. What the alpha series
needs now is use: reports of it working, or not, on real code, and of
what confused or was missing, go to the
issue tracker.
What it does
On Pythons below 3.15, activated through
autowrapt or an explicit unwrapt.install():
Your modules mark whole-module imports to defer in their own
__lazy_modules__, exactly as PEP 810 specifies: the same source is a lazy module on 3.15 and a deferred one below it, with unwrapt standing in for the interpreter’s part.Each deferred import returns a lazy proxy instead of the module. First use imports the real module and swaps it into the importing namespace, so after first use there is no residual overhead.
A JSON configuration defers imports in modules whose source you do not control.
On Python 3.15 and later the interpreter handles __lazy_modules__
natively, and unwrapt’s job narrows to applying the external
configuration of extra deferrals, without ever touching native
behaviour: with no configuration, it installs nothing. See
Python 3.15.
Alongside the deferral sits the profile mode:
UNWRAPT_PROFILE=1 records every import call of a real run, and the
report ranks candidates by cumulative time, shows the heavy modules by
self time, and draws the import chains that explain why each one
loaded, with every row marked for both routes (native 3.15 lazy
imports, and the shim). The
choosing what to defer guide is the way
to turn that report into decisions.
Start here
Using unwrapt
The profile
Reference
Source, issues and releases
unwrapt is developed on GitHub at
GrahamDumpleton/unwrapt,
under the BSD 2-Clause licence. Bug reports and feature requests go to
the issue tracker;
a report is easiest to act on when it names the unwrapt and Python
versions and includes a small application that reproduces the problem.
Releases are published to PyPI,
and each page of these docs carries an “Edit on GitHub” link to its
source under docs/ in the repository, so a documentation fix can be
raised the same way.