apipkg: Namespace Control and Lazy-Import Mechanism

3.0.2 · active · verified Sun Apr 12

apipkg is a Python package that provides a mechanism for namespace control and lazy-importing modules and objects. It allows delaying the actual import of a module until its attributes or functions are accessed, leading to improved startup performance and reduced memory consumption. The current version is 3.0.2, and it maintains an active release cadence with updates addressing compatibility and bug fixes.

Warnings

Install

Imports

Quickstart

This example demonstrates how to use `apipkg.initpkg` within a package's `__init__.py` to create a lazy-loading namespace. It defines a `mypkg` with `path` as a sub-namespace, and `Class1` and `clsattr` are only imported from their respective (simulated) modules when first accessed. The output clearly shows when the underlying modules are actually imported.

import apipkg
import sys
import os

# Simulate a package structure:
# mypkg/__init__.py
# mypkg/_mypkg/somemodule.py
# mypkg/_mypkg/othermodule.py

# Create dummy files for demonstration
os.makedirs('mypkg/_mypkg', exist_ok=True)
with open('mypkg/__init__.py', 'w') as f:
    f.write("import apipkg\napipkg.initpkg(__name__, { 'path': { 'Class1': '_mypkg.somemodule:Class1', 'clsattr': '_mypkg.othermodule:Class2.attr' } })")
with open('mypkg/_mypkg/somemodule.py', 'w') as f:
    f.write('class Class1:\n    def __init__(self):\n        print("Class1 initialized")\n        self.name = "Class1 instance"')
with open('mypkg/_mypkg/othermodule.py', 'w') as f:
    f.write('class Class2:\n    attr = 42\n    def __init__(self):\n        print("Class2 initialized")')

# Add the current directory to sys.path to allow importing 'mypkg'
sys.path.insert(0, os.getcwd())

print("Importing mypkg...")
import mypkg
print("mypkg imported.")

print("Accessing mypkg.path...")
print(mypkg.path)

print("Accessing mypkg.path.Class1 (triggers _mypkg.somemodule import)...")
instance1 = mypkg.path.Class1()
print(f"Instance name: {instance1.name}")

print("Accessing mypkg.path.clsattr (triggers _mypkg.othermodule import)...")
value = mypkg.path.clsattr
print(f"Attribute value: {value}")

# Clean up dummy files
os.remove('mypkg/__init__.py')
os.remove('mypkg/_mypkg/somemodule.py')
os.remove('mypkg/_mypkg/othermodule.py')
os.rmdir('mypkg/_mypkg')
os.rmdir('mypkg')

# Remove from sys.path and sys.modules for clean execution in a script
sys.path.pop(0)
if 'mypkg' in sys.modules: del sys.modules['mypkg']
if 'mypkg._mypkg.somemodule' in sys.modules: del sys.modules['mypkg._mypkg.somemodule']
if 'mypkg._mypkg.othermodule' in sys.modules: del sys.modules['mypkg._mypkg.othermodule']

view raw JSON →