Lazy import utilities for deferred module loading and attribute access. Truly lazy, truly late.
Project description
lateimport
Lazy import utilities for Python — defer module loading until an imported object is actually used.
Overview
lateimport provides two complementary tools:
lateimport— an explicit proxy for deferring imports in application codecreate_late_getattr— a factory for the__getattr__hook in package__init__.pyfiles, for use with dispatch-table-based lazy loading (e.g. as generated by Exportify)
Both are stdlib-only. No dependencies.
Requirements
Python 3.12+
Installation
pip install lateimport
Usage
Explicit lazy imports
Use lateimport when you want to defer a heavy import in application code. The module is not imported until the returned proxy is actually used — called, subscripted, passed to isinstance, etc.
from lateimport import lateimport
# No import happens here
numpy = lateimport("numpy")
pandas = lateimport("pandas", "DataFrame") # defers pandas.DataFrame
# Import triggered on first use
result = numpy.array([1, 2, 3])
df = pandas({"a": [1, 2]})
Proxies are thread-safe and cache the resolved object after first access.
proxy = lateimport("heavy.module", "ExpensiveClass")
proxy.is_resolved() # False
instance = proxy() # heavy.module imported, ExpensiveClass resolved
proxy.is_resolved() # True
Type annotations
LateImport[T] is a generic class. Annotating a variable with the resolved type gives you full type-checking and autocompletion downstream — the type checker knows that calling or accessing the proxy produces a T.
from __future__ import annotations
from typing import TYPE_CHECKING
from lateimport import LateImport, lateimport
if TYPE_CHECKING:
import numpy as np
from pandas import DataFrame
# Type checker knows ndarray() returns np.ndarray
ndarray: LateImport[np.ndarray] = lateimport("numpy", "ndarray")
arr = ndarray([1, 2, 3]) # arr: np.ndarray
# type[DataFrame] means calling the proxy produces a DataFrame instance
DataFrame: LateImport[type[DataFrame]] = lateimport("pandas", "DataFrame")
df = DataFrame({"col": [1, 2, 3]}) # df: DataFrame
The TYPE_CHECKING guard keeps the imports from executing at runtime — you get static type information without the import cost, which is the whole point.
For types that are always available no guard is needed:
from pathlib import Path
from lateimport import LateImport, lateimport
MkPath: LateImport[type[Path]] = lateimport("pathlib", "Path")
p = MkPath("/tmp/out") # p: Path
Package-level lazy __getattr__
For packages using a dispatch-table pattern (e.g. generated by Exportify), create_late_getattr creates a __getattr__ hook that imports attributes on demand:
# mypackage/__init__.py
from types import MappingProxyType
from lateimport import create_late_getattr
# NOTE: for IDE support, import any dynamic imports in a TYPE_CHECKING block:
from typing import TYPE_CHECKING:
from mypackage.core.models import MyClass
from mypackage.utils.helpers import my_function
from mypackage import SubModule
_dynamic_imports = MappingProxyType({
"MyClass": ("mypackage.core", "models"),
"my_function": ("mypackage.utils", "helpers"),
# for the current package you can just use __spec__.parent:
"SubModule": (__spec__.parent, "__module__"),
})
__getattr__ = create_late_getattr(_dynamic_imports, globals(), __name__)
__all__ = ("MyClass", "my_function", "SubModule")
# Make sure dir calls use __all__ and not globals:
__dir__ = lambda: list(__all__)
The dispatch tuple is (package, submodule):
- Normal attributes: imports
package.submoduleand returnsgetattr(submodule, attr_name) "__module__": imports the submodule itself as the attribute (import_module(f".{attr_name}", package=package))
Resolved attributes are cached in globals() so subsequent accesses are direct.
API
lateimport(module_name, *attrs) -> LateImport[T]
Create a lazy proxy for module_name. Optional attrs are an attribute chain traversed after import. The function is generic — annotate the variable as LateImport[T] to propagate the resolved type to callers.
lateimport("os") # proxy for the os module
lateimport("os.path", "join") # proxy for os.path.join
lateimport("mypackage", "A", "B") # proxy for mypackage.A.B
class LateImport[T]
The generic proxy class returned by lateimport. Annotate the variable with LateImport[T] to tell the type checker what type the proxy resolves to — __call__ and _resolve() are typed to return T. Supports call, attribute access, dir(), and repr(). Thread-safe.
| Method | Description |
|---|---|
is_resolved() |
True if the import has been triggered |
_resolve() |
Force immediate resolution and return the object (typed as T) |
create_late_getattr(dynamic_imports, module_globals, module_name)
Create a __getattr__ function for package-level lazy loading.
| Parameter | Type | Description |
|---|---|---|
dynamic_imports |
MappingProxyType[str, tuple[str, str]] |
Dispatch table |
module_globals |
dict[str, object] |
globals() of the calling module |
module_name |
str |
__name__ of the calling module |
INTROSPECTION_ATTRIBUTES
frozenset of dunder attribute names that are resolved immediately rather than proxied (e.g. __doc__, __name__, __module__). Available for reference when implementing custom proxy patterns.
License
MIT OR Apache-2.0 — see LICENSE-MIT and LICENSE-Apache-2.0.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lateimport-0.1.0.tar.gz.
File metadata
- Download URL: lateimport-0.1.0.tar.gz
- Upload date:
- Size: 38.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8da4efbaaa21f4e6f42ef072b7ccd8a16c9bcd1cfc8640de8577419942f327aa
|
|
| MD5 |
be765c50b7b6058ff5f89e921da3b4da
|
|
| BLAKE2b-256 |
796236f8a340120e167889ec3760d8dc61af101779fbf601a3d400c3ac829172
|
Provenance
The following attestation bundles were made for lateimport-0.1.0.tar.gz:
Publisher:
publish.yml on knitli/lateimport
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lateimport-0.1.0.tar.gz -
Subject digest:
8da4efbaaa21f4e6f42ef072b7ccd8a16c9bcd1cfc8640de8577419942f327aa - Sigstore transparency entry: 977430242
- Sigstore integration time:
-
Permalink:
knitli/lateimport@1b2f200fc64baa9f54baba4d7dc60e13cd3d2046 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/knitli
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1b2f200fc64baa9f54baba4d7dc60e13cd3d2046 -
Trigger Event:
push
-
Statement type:
File details
Details for the file lateimport-0.1.0-py3-none-any.whl.
File metadata
- Download URL: lateimport-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6eb33d131f72722a9e3ca9fba33233abafd77e1fa7f7e0cd9292bd368928dd37
|
|
| MD5 |
3f4d5f6dc7adab5c8a7ff017986ac4c0
|
|
| BLAKE2b-256 |
ffb5435c78e583f3d53bc6bccad2fd65aacea158a244624eb0505d4fd8c97a61
|
Provenance
The following attestation bundles were made for lateimport-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on knitli/lateimport
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lateimport-0.1.0-py3-none-any.whl -
Subject digest:
6eb33d131f72722a9e3ca9fba33233abafd77e1fa7f7e0cd9292bd368928dd37 - Sigstore transparency entry: 977430302
- Sigstore integration time:
-
Permalink:
knitli/lateimport@1b2f200fc64baa9f54baba4d7dc60e13cd3d2046 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/knitli
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1b2f200fc64baa9f54baba4d7dc60e13cd3d2046 -
Trigger Event:
push
-
Statement type: