Skip to main content

delayed-import

delayed-import is a Python library that lets you selectively change the behavior of import statements to delay the actual import action. It can be enabled/disabled per module and should work mostly transparently otherwise.

Installation

Install delayed-import with any Python package manager.

Motivation

Suppose you have a module mod1 that imports a library function, defines a function of its own, and optionally calls both on some user input when executed as a script:

import sys

from package1.package2 import func1

def func2(text: str) -> str:
    return f"func2: {text}"

if __name__ == "__main__":
    user_input = sys.argv[1]
    print(func1(user_input))
    print(func2(user_input))

When executing this as a script, it works as expected. But maybe another module would like to import mod1 as a library and only call func2. To do so, func1 must first be imported, which may depending on the structure of the containing packages entail a lot of extra work.

To make this module lighter to import, you could move the import of func1 to inside the if __name__ == "__main__": block. But this is not always an easy refactor and might lead to many repeated import statements. This library offers an alternative, by making the import delayed: this means that when you write the import statement, the name func1 is assigned a wrapper object that will resolve to the actual func1 when it is used. The lazy-object-proxy package is used for this.

The modified example would look like this:

import delayed_import

# Enable delayed imports in the current module and all submodules.
delayed_import.enable(__name__)

import sys

from package1.package2 import func1

def func2(text: str) -> str:
    return f"func2: {text}"

if __name__ == "__main__":
    user_input = sys.argv[1]
    print(func1(user_input))
    print(func2(user_input))

This code will function the same, except that the imports of package1 and package1.package2 are delayed until the moment they are used, when func1 is called. That means that if this file is imported as a module, they will not be imported at all. (Actually, the import of sys is similarly delayed, though it is likely already imported by this point.) It would be roughly equivalent to the following:

def func2(text: str) -> str:
    return f"func2: {text}"

if __name__ == "__main__":
    import sys
    user_input = sys.argv[1]
    from package1.package2 import func1
    print(func1(user_input))
    print(func2(user_input))

Usage

To use in a module, import the library and call enable with the module name:

import delayed_import

delayed_import.enable(__name__)

This makes all import statements that are executed in that module from that point on delayed. It is possible to later disable delayed imports by calling disable with the module name.

import delayed_import

delayed_import.enable(__name__)

# ...delayed imports...

delayed_import.disable(__name__)

# ...regular imports...

A block of imports can also be delayed by using enable as a context manager.

import delayed_import

with delayed_import.enable(__name__):
    # ...delayed imports...

# ...regular imports...

When enabling delayed imports, this will also affect submodules, allowing you to enable/disable them for entire code trees at once. You can mix enabling and disabling, i.e. if a enables them, and a.b disables them, then in a.c they will be enabled and in a.b.d they will be disabled.

It is possible to enable delayed imports for any module, not just for the current one. However, since delayed imported objects are not equivalent to their non-delayed equivalents, it might be necessary to adjust the importing code to take this difference into account.

Caveats

The main caveats have to do with the wrapping of the imported objects. This means that the imported object is not actually the same object as the one in the imported module. However, lazy-object-proxy wraps the object pretty thouroughly, so this is rarely observable. The biggest difference is that referential equality will be broken. So the following will fail with an AssertionError:

import delayed_import

delayed_import.enable(__name__)

# x1 wraps x, to delay the import.
from package1 import x as x1

delayed_import.disable(__name__)

# x2 is the real x, since delayed imports are disabled.
from package1 import x as x2

# This will work...
assert x1 == x2

# ...but this will fail!
assert x1 is x2

Moreover, because a new wrapper is created for every import statement, importing the same object twice will also not compare equal with is.

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

License

MIT

Acknowledgements

README template from https://www.makeareadme.com.

Metadata

Release files for delayed-import 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for delayed-import 0.1.0
File Size Uploaded Provenance Actions
delayed_import-0.1.0.tar.gz 12.8 kB With provenance Details for delayed_import-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for delayed-import 0.1.0
File Interpreter ABI Platform Actions
delayed_import-0.1.0-py3-none-any.whl Python 3 none any Details for delayed_import-0.1.0-py3-none-any.whl

Total release size: 20.9 kB

Release files / delayed_import-0.1.0.tar.gz

Download URL delayed_import-0.1.0.tar.gz
Size 12.8 kB
Tags Source
SHA-256 checksum
How to use checksums
1389e1c6a06804d702e18216ba312d8e6ce1570c7c041c1550b6b4cd8d426b76
BLAKE2b-256 checksum
How to use checksums
73efdcbeb4e98c60891b9b8bd4ac690097c529ea7ff1bac6dfae1a6ee87b64e1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 28, 2025.

Transparency log

Release files / delayed_import-0.1.0-py3-none-any.whl

Download URL delayed_import-0.1.0-py3-none-any.whl
Size 8.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3b249a885f347a00a1ed64d3340842c45d154fc1216ec20134b0e762b27746b9
BLAKE2b-256 checksum
How to use checksums
fcd5fb603b40be4b3bf5d2dd31e4db3d0c5fe72b0d1a7ef7a9ebdf28e53f5bec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.12.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 28, 2025.

Transparency log

Security for delayed-import 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for delayed_import-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 28, 2025.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page