https://github.com/yostealth/dynamic-import
Dynamic or Lazy Import Python Module
https://github.com/yostealth/dynamic-import
Last synced: 10 months ago
JSON representation
Dynamic or Lazy Import Python Module
- Host: GitHub
- URL: https://github.com/yostealth/dynamic-import
- Owner: YoSTEALTH
- License: cc0-1.0
- Created: 2018-08-06T22:07:00.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2025-02-12T18:52:35.000Z (over 1 year ago)
- Last Synced: 2025-02-12T19:39:40.356Z (over 1 year ago)
- Language: Python
- Homepage: https://pypi.org/project/dynamic-import/
- Size: 134 KB
- Stars: 2
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.rst
- License: LICENSE.txt
Awesome Lists containing this project
README
|test-status| |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 import `` 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:
.. code-block:: bash
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
____________________________
.. code-block:: bash
python3 -m pip install --upgrade git+https://github.com/YoSTEALTH/Dynamic-Import
Usage
-----
.. code-block:: python
# .//__init__.py
from dynamic_import import importer
importer()
``importer()`` options
______________________
.. code-block:: python
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
-------
.. code-block:: python
# ./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.
.. code-block:: python
# ./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
.. code-block:: python
# ./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
.. code-block:: python
# ./example/classes/__init__.py
__all__ = ['MyClass']
class MyClass:
pass
Calling
_______
.. code-block:: python
# ./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-.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 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()`` 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`_
.. _pip: https://pip.pypa.io/en/stable/getting-started/
.. _Read more: https://github.com/YoSTEALTH/Dynamic-Import/blob/master/LICENSE.txt
.. _Liburing: https://github.com/YoSTEALTH/Liburing
.. |test-status| image:: https://github.com/yostealth/dynamic-import/actions/workflows/test.yml/badge.svg?branch=master&event=push
:target: https://github.com/yostealth/dynamic-import/actions/workflows/test.yml
:alt: Test status
.. |downloads| image:: https://img.shields.io/pypi/dm/dynamic_import
:alt: PyPI - Downloads