Lazy Bear
Lazy Bear is a lightweight toolkit for deferring Python imports until the first time you actually need them. Keep startup fast, trim optional dependencies, and expose a clean API without fighting import order.
Highlights
- Drop-in
lazy("package.module")helper that mirrors a regular module object once touched. LazyLoader.to()andLazyLoader.to_many()for lazily binding one or more attributes without importing the whole module up front.LazyAttr.valuefor grabbing the underlying attribute (dicts, constants, classes) without changing call semantics.- Ideally the attribute would just be extracted but there are some issues when the item is defined within a local scope.
- Thread-safe module caching that updates
sys.modulesand the caller's globals exactly once. - Debug-friendly repr and
dir()support so interactive sessions stay intuitive even before loading. - Batteries-included CLI with version info, environment diagnostics, and release bump helpers.
Installation
Requires Python 3.13 or newer.
pip install lazy-bear
With uv:
uv tool install lazy-bear
Quick Start
from lazy_bear import lazy
json = lazy("json") # nothing imported yet
payload = {"hello": "lazy bear"}
print(json.dumps(payload, sort_keys=True))
# Module is imported the first time .dumps is accessed.
Under the hood lazy() returns a LazyLoader (a types.ModuleType subclass). Once you touch an attribute it:
- Imports the target module.
- Registers it in both
sys.modulesand the globals of the caller. - Proxies the module so future access is indistinguishable from a normal import.
Lazily Accessing Attributes
Sometimes you only need a specific callable or attribute, not the whole module namespace:
from lazy_bear import LazyAttr, lazy
console = lazy("rich.console")
Console: LazyAttr = console.to("Console")
if __name__ == "__main__":
rich_console = Console(width=100) # `rich.console` is imported here
rich_console.print("[bold green]Hello from Lazy Bear![/]")
Need multiple attributes or callables? Use to_many:
math = lazy("math")
sqrt_attr, pow_attr = math.to_many("sqrt", "pow")
print(sqrt_attr(25)) # LazyAttr stays callable
pow_func = pow_attr.value # or pow_attr.unwrap()
print(pow_func(2, 3))
LazyAttr proxies most dunder methods (__call__, __iter__, __getitem__, etc.), so lazily loaded attributes behave just like the originals.
When you need the underlying object—say a dictionary of settings—forgo calling and reach for .value (or its alias .unwrap()):
env = lazy("os").to("environ").value # returns the real os._Environ mapping
letters = lazy("string").to("ascii_letters").unwrap() # works for constants too
class Override
There is a class override in the LazyAttr class in order to get things like isinstance() support to work as expected. It isn't
100% ideal but allows the wrapper to act as the wrapped object during the moments before the wrapper is destroyed.
Metadata
Release files for lazy-bear 0.0.20
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lazy_bear-0.0.20-py3-none-any.whl | Python 3 | none | any | Details |
Release files / lazy_bear-0.0.20-py3-none-any.whl
| Download URL | lazy_bear-0.0.20-py3-none-any.whl |
|---|---|
| Size | 19.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dd040c63bfe746f46d0588bae3e1ccc9b25d7a2ee2e766d50529d7553ac3471b
|
|
BLAKE2b-256 checksum How to use checksums |
cce286fb06c7dd5057c9062be1f18c4052a1838101bce0c0843e9af0c27f40bc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.
Transparency log