Install & Compatibility
Where this runs
tested against v3.0.2 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.016s · 17.8MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 1.5s · import 0.014s · 18MB
16MB installed
● package 16MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
initpkg
✓ from apipkg import initpkg
✗ import apipkg
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']
Debug
Known issues
breakingVersion 3.0.0 dropped support for older Python versions, requiring Python 3.7 or newer. Users on older Python environments will need to remain on `apipkg < 3.0.0`.fixUpgrade Python to 3.7+ or pin `apipkg` to a compatible version (e.g., `apipkg<3.0.0`).
affects: < 3.0.0
gotchaVersions prior to 2.1.0 contained race conditions during module import and attribute creation, which could lead to unexpected behavior or import failures, especially in multi-threaded contexts or complex import graphs. Version 2.1.0 (and subsequent versions) include fixes for these issues.fixUpgrade to `apipkg >= 2.1.0` to benefit from race condition fixes.
affects: < 2.1.0
gotchaOlder `apipkg` versions (especially pre-2.0.0, but also affecting some 3.x versions bundled with `py` library) might not correctly preserve the `__spec__` attribute, leading to `KeyError: '__spec__'` errors when used with newer Python versions (3.7+, 3.11+) and tools like `pytest` or `tox`. Version 2.0.0 introduced `__spec__` transfer, and further compatibility fixes have been integrated in later 3.x releases.fixEnsure you are using `apipkg >= 3.0.0` with Python 3.7+ to avoid `__spec__` related issues. If vendoring, ensure the vendored version includes relevant fixes.
affects: < 2.0.0, potentially some 3.x versions with specific Python 3.11+ setups
gotchaVersion 3.0.2 introduced a fix to make import paths 'vendoring-friendly'. If you are vendoring `apipkg` into your project, older versions might encounter issues related to incorrect import paths.fixUpdate to `apipkg >= 3.0.2` if you are vendoring the library.
affects: < 3.0.2
Upgrade
Version history
3.0.2latest on PyPI · released Sep 19, 2023
Audit
Dependencies
No dependency data recorded yet.