Skip to main content

Let Dynamic Import handle your projects(package) import needs. Enables you to dynamically(lazily) import module as needed on run-time.

Project description

Test status PyPI - Downloads

Dynamic Import

Let Dynamic Import handle your projects(package) import needs. Enables you to dynamically(lazily) import module as needed within the project and for external usage on run-time.

  • Place importer() into top __init__.py file and forget about where variable, function, class, … are located.

  • Just call from <package> import <variable> while coding and when end-user calls from your project. All names are accessible at top level, easy to remember.

  • Move/rename file within your project? No problem, auto updates.

  • Supports .py and .so (experimental)

  • Saves memory(for medium to large projects).

Ultimate worry free management comfort as your project grows from small to large.

Requires

  • Python 3.8+

  • Linux, MacOS

Install, update & uninstall

Use pip to:

python3 -m pip install dynamic-import            # install

python3 -m pip install --upgrade dynamic-import  # update

python3 -m pip uninstall dynamic-import          # uninstall

Install directly from GitHub

python3 -m pip install --upgrade git+https://github.com/YoSTEALTH/Dynamic-Import

Usage

# ./<package>/__init__.py
from dynamic_import import importer

importer()

importer() options

importer(cache=False)  # disable & remove cache file (for temporary use only!)

importer(recursive=False)  # do not scan sub-directories

# exclude `.py, .so` file
importer(exclude_file='file.py')                          # single
importer(exclude_file=('one.py', 'sub-dir/two.py', ...))  # multiple

# exclude sub-directory
importer(exclude_dir='sub-dir')                        # single
importer(exclude_dir=('sub-dir', 'sub/sub-dir', ...))  # multiple

Example

# ./example/pkg/__init__.py
from dynamic_import import importer


__version__ = '1.2.3'  # if need to use special name place it above `importer()`

importer()  # only need to call `importer()` once inside main `__init__.py` file.

# note: `importer()` will scan all package directory and sub-directories for `.py, .so`
# files and cache import names for dynamic use.
# ./example/pkg/var.py
import sys

# just like normal import if `__all__` is not defined, `my_var` will be included.
# Also `sys` will not be included.

my_var = sys.version_info.major
# ./example/pkg/functions/myfunction.py
from pkg import my_var
# all import names are available at higher level,
# no need for `from ..example.var import my_var`

__all__ = 'my_function'  # using just string for single name is ok


def my_function():
    return my_var + 1
# ./example/classes/__init__.py

__all__ = ['MyClass']


class MyClass:
    pass

Calling

# ./example/calling.py
# import all 3 names regardless of where module is located
from pkg import my_var, my_function, MyClass

# or
import pkg

MyClass()
print(my_var, pkg.my_var is my_var) # 3 True
print(my_function())                # 4
print(dir(pkg))                     # ['my_var', 'my_function', 'MyClass', ...]

Note

  • Only need to call importer() once inside __init__.py file.

  • All sub-directories will be scanned for .py, .so file as recursive=True by default.

  • Use exclude_dir to list sub-directories you would like to avoid scanning.

  • You can still use normal static/relative import.

  • For one word import name you can use string e.g. __all__ = 'function' vs __all__ = ('function',)

  • All import names must be unique.

  • Cache can be disabled & removed by using importer(cache=False)

  • Cached temporary files are stored in ./__pycache__/__init__.importer-<python-version>.pyc

  • You can move or rename any .py file within project directory or sub-directory and import will not break.

  • Special name e.g: __something__ are ignored. If need to use special name place it above importer() e.g.``__version__ = ‘1.2.3’; importer()``

  • Using from <package> import * is not recommended unless you want to load all the modules.

  • No need to have empty __init__.py inside sub-directories. Its “like” Namespace + Package combined into one! but not technically.

  • Calling dir(<package>) enables you to show all importable names without loading modules.

Experimental

  • Having module name and function name the same is ok! e.g. from pkg import my_fun while ./pkg/my_fun.py and calling my_fun() will not conflict with module name. Module will still load in the background.

  • importer() also works with certain .cpython-<...>.so .abi3.so file (only tested with cython created *.so).

  • .so should not contain any function/class that auto-run on import e.g.``run_something()``

  • Visit Liburing to see project using Dynamic Import with .so files in action.

License

Free, Public Domain (CC0). Read more

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dynamic_import-2024.5.2.tar.gz (27.7 kB view hashes)

Uploaded Source

Built Distribution

dynamic_import-2024.5.2-py3-none-any.whl (19.1 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page