Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

55 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ultralytics logo

⚡️ autoimport: Explicit Lazy Module Imports

autoimport defers execution of a Python module until its first attribute access. It builds on Python's standard importlib loader protocol, preserving the canonical module object and its identity in sys.modules.

The ultralytics-autoimport package supports Python 3.8 through 3.14.

autoimport CI Ultralytics Actions PyPI - Version Downloads PyPI - Python Version

📦 Installation

pip install ultralytics-autoimport

💻 Usage

Replace a module import with an explicit lazy assignment:

import time

from autoimport import lazy_import

t0 = time.perf_counter()
torch = lazy_import("torch")  # Finds torch now, but does not execute torch/__init__.py yet
print(f"Setup: {time.perf_counter() - t0:.3f}s")

t1 = time.perf_counter()
torch.cuda.is_available()  # First attribute access executes and initializes torch
print(f"First use: {time.perf_counter() - t1:.3f}s")

torch.tensor([1, 2, 3])  # Later attributes use the fully initialized module normally

Aliases and dotted modules are explicit strings:

np = lazy_import("numpy")
linalg = lazy_import("numpy.linalg")

If the requested module is already imported, lazy_import() returns the existing object unchanged. Module discovery happens immediately, so a misspelled or unavailable module raises ModuleNotFoundError at the lazy_import() call. For dotted names, Python may import parent packages while finding the requested child module.

⚠️ Scope and Limitations

lazy_import() deliberately supports modules only. It does not emulate arbitrary from ... import ... bindings:

# Supported
pathlib = lazy_import("pathlib")
path = pathlib.Path("models")

# Not provided: transparent lazy classes, functions, or constants
# Path = lazy_import("pathlib.Path")

Deferring a module also defers its import-time side effects and any exception raised while executing its body. Those effects or errors occur on first attribute access instead of at the assignment. If code immediately accesses the module after lazy_import(), there is no startup benefit.

First execution of lazy module bodies is serialized process-wide. This prevents two lazy modules from deadlocking each other during concurrent circular initialization, but it also means unrelated first accesses cannot initialize in parallel. Module bodies run while that shared reentrant lock is held, so applications should avoid coordinating lazy first access with other threads during import-time synchronization.

The discovered loader must support exec_module(), and its module object must permit __class__ reassignment. These are the same compatibility requirements as Python's importlib.util.LazyLoader; incompatible custom loaders fail during lazy_import() instead of returning a partial proxy.

Versions before 0.1.0 exposed a with lazy(): context manager that replaced builtins.__import__. That design could not preserve normal Python behavior for aliases, function-local imports, dotted imports, or objects imported with from ... import ..., and it affected imports in every thread. Replace it with explicit module assignments.

🐍 Python 3.15 and PEP 810

Python 3.15 adds native lazy imports through accepted PEP 810. Its interpreter-supported syntax can lazily bind both modules and imported attributes:

lazy from pathlib import Path

lazy import torch

PEP 810 also provides a migration form that keeps ordinary import statements:

>>> __lazy_modules__ = {"numpy", "torch"}
>>> import numpy as np
>>> import torch

On Python 3.15, the listed imports are lazy. Earlier Python versions ignore __lazy_modules__ and import them eagerly, which lets libraries adopt the declaration before dropping older versions. Native lazy imports are the preferred long-term solution because the interpreter can replace a lazy binding with any real module, class, function, or constant before Python code uses it. autoimport remains a narrow module-only option for Python 3.8 through 3.14.

🛠️ Development

uv pip install -e .
python -m unittest discover tests -v
ruff format .
ruff check .

💡 Contribute

Ultralytics thrives on community collaboration, and we deeply value your contributions! Whether it's reporting bugs, suggesting features, or submitting code changes, your involvement is crucial.

  • Reporting Issues: Encounter a bug? Please report it on GitHub Issues.
  • Feature Requests: Have an idea for improvement? Share it via GitHub Issues.
  • Pull Requests: Want to contribute code? Please read our Contributing Guide first, then submit a Pull Request.
  • Feedback: Share your thoughts and experiences by participating in our official Survey.

A heartfelt thank you 🙏 goes out to all our contributors! Your efforts help make Ultralytics tools better for everyone.

Ultralytics open-source contributors

📄 License

Ultralytics offers two licensing options to accommodate diverse needs:

  • AGPL-3.0 License: Ideal for students, researchers, and enthusiasts passionate about open collaboration and knowledge sharing. This OSI-approved open-source license promotes transparency and community involvement. See the LICENSE file for details.
  • Enterprise License: Designed for commercial applications, this license permits the seamless integration of Ultralytics software and AI models into commercial products and services, bypassing the copyleft requirements of AGPL-3.0. For commercial use cases, please inquire about an Ultralytics Enterprise License.

📮 Contact

For bug reports or feature suggestions, please use GitHub Issues. For general questions, discussions, and community support, join our Discord server!


Ultralytics GitHub space Ultralytics LinkedIn space Ultralytics Twitter space Ultralytics YouTube space Ultralytics TikTok space Ultralytics BiliBili space Ultralytics Discord

About

Lightweight Python lazy imports that defer module loading to reduce startup time and initial memory use.

Topics

Resources

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

Sponsor this project

Used by

Contributors

Languages

Generated from ultralytics/template