Skip to content

lazy_loader

util.lazy_loader

모듈이나 객체를 실제 사용할 때까지 import를 지연시키는 클래스를 정의합니다.

_LazyModule

_LazyModule(local_name: str, module_name: str, globals: Dict[str, Any])

Bases: ModuleType

Source code in SaigeToolkit/util/lazy_loader.py
def __init__(
    self,
    local_name: str,
    module_name: str,
    globals: Dict[str, Any],
):
    super().__init__(name=module_name)

    self._local_name = local_name
    self._module_name = module_name
    self._globals = globals

_local_name instance-attribute

_local_name = local_name

_module_name instance-attribute

_module_name = module_name

_globals instance-attribute

_globals = globals

_load

_load() -> ModuleType
Source code in SaigeToolkit/util/lazy_loader.py
def _load(self) -> ModuleType:
    module = import_module(name=self._module_name)
    self._globals[self._local_name] = module
    self.__dict__.update(module.__dict__)
    return module

__getattr__

__getattr__(name: str) -> Any
Source code in SaigeToolkit/util/lazy_loader.py
def __getattr__(self, name: str) -> Any:
    module = self._load()
    return getattr(module, name)

__repr__

__repr__() -> str
Source code in SaigeToolkit/util/lazy_loader.py
def __repr__(self) -> str:
    # For debugging
    return f"<lazy module '{self._module_name}'>"

_LazyClassMeta

_LazyClassMeta(name, bases, namespace)

Bases: type

Source code in SaigeToolkit/util/lazy_loader.py
def __init__(cls, name, bases, namespace):
    super().__init__(name, bases, namespace)
    cls._local_name = namespace["local_name"]
    cls._class_name = namespace["class_name"]
    cls._module_name = namespace["module_name"]
    cls._globals = namespace["globals"]
    cls._class = None

_load

_load()
Source code in SaigeToolkit/util/lazy_loader.py
def _load(cls):
    module = import_module(name=cls._module_name)
    _class = getattr(module, cls._class_name)
    cls._globals[cls._local_name] = _class
    cls._class = _class
    return _class

__call__

__call__(*args, **kwargs)
Source code in SaigeToolkit/util/lazy_loader.py
def __call__(cls, *args, **kwargs):
    _class = cls._class or cls._load()
    return _class(*args, **kwargs)

__getattr__

__getattr__(name)
Source code in SaigeToolkit/util/lazy_loader.py
def __getattr__(cls, name):
    _class = cls._class or cls._load()
    return getattr(_class, name)

__repr__

__repr__() -> str
Source code in SaigeToolkit/util/lazy_loader.py
def __repr__(cls) -> str:
    # For debugging
    return f"<lazy class '{cls._module_name}.{cls._class_name}'>"

_resolve_package

_resolve_package(package: Optional[str], parent_globals: Dict[str, Any]) -> Optional[str]
Source code in SaigeToolkit/util/lazy_loader.py
def _resolve_package(package: Optional[str], parent_globals: Dict[str, Any]) -> Optional[str]:
    if package is None:
        return None
    elif package.startswith("."):
        base_package = parent_globals.get("__package__")
        if base_package is None:
            raise ImportError("attempted relative import with no known parent package")
        return base_package if package == "." else base_package + package
    else:
        return package

lazy_module

lazy_module(name_as: str, /, import_from: Optional[str] = None, name: Optional[str] = None, *, globals: Optional[Dict[str, Any]] = None)

A wrapper for modules that delays the import until it is needed. After the module is imported, it is stored in the namespace.

Parameters:

  • name_as (str) –

    The name of the module in the namespace.

  • import_from (Optional[str], default: None ) –

    The base package of the module.

  • name (Optional[str], default: None ) –

    The name of the module to import. Defaults to the value of name_as.

  • globals (dict, default: None ) –

    The current namespace (pass globals() here).

Usage
# import numpy as np
np = lazy_module("np", name="numpy", globals=globals())
print(np)  # <lazy module 'numpy'>

np.random.rand(5)  # `numpy` is imported here
print(np)  # <module 'numpy' from '...'>

# import torch
torch = lazy_module("torch", globals=globals())

# from torchvision.models import resnet
resnet = lazy_module("resnet", "torchvision.models", globals=globals())

# from torch.nn import functional as F
F = lazy_module("F", "torch.nn", "functional", globals=globals())

# from .engine import api
api = lazy_module("api", ".engine", globals=globals())
Note

The name_as parameter should match the name of the variable in the namespace.

Source code in SaigeToolkit/util/lazy_loader.py
def lazy_module(
    name_as: str,
    /,
    import_from: Optional[str] = None,
    name: Optional[str] = None,
    *,
    globals: Optional[Dict[str, Any]] = None,
):
    """
    A wrapper for modules that delays the import until it is needed.
    After the module is imported, it is stored in the namespace.

    Parameters:
        name_as (str): The name of the module in the namespace.
        import_from (Optional[str]): The base package of the module.
        name (Optional[str]): The name of the module to import. Defaults to the value of `name_as`.
        globals (dict): The current namespace (pass `globals()` here).

    Usage:
        ```python
        # import numpy as np
        np = lazy_module("np", name="numpy", globals=globals())
        print(np)  # <lazy module 'numpy'>

        np.random.rand(5)  # `numpy` is imported here
        print(np)  # <module 'numpy' from '...'>

        # import torch
        torch = lazy_module("torch", globals=globals())

        # from torchvision.models import resnet
        resnet = lazy_module("resnet", "torchvision.models", globals=globals())

        # from torch.nn import functional as F
        F = lazy_module("F", "torch.nn", "functional", globals=globals())

        # from .engine import api
        api = lazy_module("api", ".engine", globals=globals())
        ```

    Note:
        The `name_as` parameter should match the name of the variable in the namespace.
    """
    name = name or name_as
    globals = globals or sys._getframe(1).f_globals
    package = _resolve_package(import_from, globals)
    module_name = name if package is None else f"{package}.{name}"
    return _LazyModule(name_as, module_name, globals)

lazy_class

lazy_class(name_as: str, /, import_from: str, name: Optional[str] = None, *, globals: Optional[Dict[str, Any]] = None)

A wrapper for classes that delays the import until it is needed. After the class is imported, it is stored in the namespace.

Parameters:

  • name_as (str) –

    The name of the class in the namespace.

  • import_from (str) –

    The module path of the class.

  • name (Optional[str], default: None ) –

    The name of the class to import. Defaults to the value of name_as.

  • globals (dict, default: None ) –

    The current namespace (pass globals() here).

Usage
# from torch.nn import Linear
Linear = lazy_class("Linear", "torch.nn", globals=globals())
print(Linear)  # <lazy class 'torch.nn.Linear'> (cannot resolve the actual path)

linear = Linear(3, 4)  # `Linear` is imported here
print(linear)  # Linear(in_features=3, out_features=4, bias=True)
print(Linear)  # <class 'torch.nn.modules.linear.Linear'>

# from torchvision.models.resnet import ResNet as _ResNet
_ResNet = lazy_module("_ResNet", "torchvision.models.resnet", "ResNet", globals=globals())

# from .engine.api import Trainer
Trainer = lazy_class("Trainer", ".engine.api", globals=globals())
trainer = Trainer.build(...)
Note

The name_as parameter should match the name of the variable in the namespace.

Warning

The only safe way to use this is class attribute access or instantiation. Do not use this with class-level methods like isinstance or issubclass.

Source code in SaigeToolkit/util/lazy_loader.py
def lazy_class(
    name_as: str,
    /,
    import_from: str,
    name: Optional[str] = None,
    *,
    globals: Optional[Dict[str, Any]] = None,
):
    """
    A wrapper for classes that delays the import until it is needed.
    After the class is imported, it is stored in the namespace.

    Parameters:
        name_as (str): The name of the class in the namespace.
        import_from (str): The module path of the class.
        name (Optional[str]): The name of the class to import. Defaults to the value of `name_as`.
        globals (dict): The current namespace (pass `globals()` here).

    Usage:
        ```python
        # from torch.nn import Linear
        Linear = lazy_class("Linear", "torch.nn", globals=globals())
        print(Linear)  # <lazy class 'torch.nn.Linear'> (cannot resolve the actual path)

        linear = Linear(3, 4)  # `Linear` is imported here
        print(linear)  # Linear(in_features=3, out_features=4, bias=True)
        print(Linear)  # <class 'torch.nn.modules.linear.Linear'>

        # from torchvision.models.resnet import ResNet as _ResNet
        _ResNet = lazy_module("_ResNet", "torchvision.models.resnet", "ResNet", globals=globals())

        # from .engine.api import Trainer
        Trainer = lazy_class("Trainer", ".engine.api", globals=globals())
        trainer = Trainer.build(...)
        ```

    Note:
        The `name_as` parameter should match the name of the variable in the namespace.

    Warning:
        The only safe way to use this is class attribute access or instantiation.
        Do not use this with class-level methods like `isinstance` or `issubclass`.
    """
    name = name or name_as
    globals = globals or sys._getframe(1).f_globals
    module_name = _resolve_package(import_from, globals)
    namespace = {
        "local_name": name_as,
        "class_name": name,
        "module_name": module_name,
        "globals": globals,
    }
    return _LazyClassMeta(name_as, (object,), namespace)