Skip to main content

OpenSSF Best Practices

Import Tracker

Import Tracker is a Python package offering a number of capabilities related to tracking and managing optional dependencies in Python projects. Specifically, this project enables developers to:

  • Track the dependencies of a python project to map each module within the project to the set of dependencies it relies on. This can be useful for debugging of dependencies in large projects.

  • Enable lazy import errors in a python projects to prevent code from crashing when uninstalled imports are imported, but not utilized. This can be helpful in large projects, especially those which incorporate lots of hierarchical wild imports, as importing the top level package of such projects can often bring a lot of heavy dependencies into sys.modules.

  • Programmatically determine the install_requires and extras_require arguments to setuptools.setup where the extras sets are determined by a set of modules that should be optional.

Table of contents

Running Import Tracker

To run import_tracker against a project, simply invoke the module's main:

python3 -m import_tracker --name <my_module>

The main supports the following additional arguments:

  • --package: Allows --name to be a relative import (see importlib.import_module)
  • --indent: Indent the output json for pretty printing
  • --log_level: Set the level of logging (up to debug4) to debug unexpected behavior
  • --submodules: List of sub-modules to recurse on (or full recursion when no args given)
  • --track_import_stack: Store the stack trace of imports belonging to the tracked module
  • --detect_transitive: Mark each dependency as either "direct" (imported directly) or "transitive" (inherited from a direct import)
  • --full_depth: Track all dependencies, including transitive dependencies of direct third-party deps
  • --show_optional: Show whether each dependency is optional or required

Integrating import_tracker into a project

When using import_tracker to implement optional dependencies in a project, there are two steps to take:

  1. Enable lazy_import_errors for the set of modules that should be managed as optional
  2. Use setup_tools.parse_requirements in setup.py to determine the install_requires and extras_require arguments

In the following examples, we'll use a fictitious project with the following structure:

my_module/
├── __init__.py
├── utils.py
└── widgets
    ├── __init__.py
    ├── widget1.py
    └── widget2.py

Enabling lazy_import_errors

The import_tracker.lazy_import_errors function can be invoked directly to enable lazy import errors globally, or used as a context manager to enable them only for a selcted set of modules.

To globally enable lazy import errors, my_module/__init__.py would look like the following:

# Globally enable lazy import errors
from import_tracker import lazy_import_errors
lazy_import_errors()

from . import utils, widgets

Alternately, applying lazy import error semantics only to the widgets would look like the following:

from import_tracker import lazy_import_errors

# Require all downstream imports from utils to exist
from . import utils

# Enable lazy import errors for widgets
with lazy_import_errors():
    from . import widgets

When using lazy import errors, there are two ways to customize the error message that is raised when a failed import is used:

    1. The get_extras_modules argument takes a function which returns a Set[str] of the module names that are tracked as extras. If the import error is triggered within a module that is managed as an extras set, the error message is updated to include instructions on which extras set needs to be installed.
  1. The make_error_message argument allows the caller to specify a fully custom error message generation function.

Using setup_tools.parse_requirements

To take advantage of the automatic dependency parsing when building a package, the setup.py would look like the following:

import import_tracker
import os
import setuptools

# Determine the path to the requirements.txt for the project
requirements_file = os.path.join(os.path.dirname(__file__), "requirements.txt")

# Parse the requirement sets
install_requires, extras_require = import_tracker.setup_tools.parse_requirements(
    requirements_file=requirements_file,
    library_name="my_module",
    extras_modules=[
        "my_module.widgets.widget1",
        "my_module.widgets.widget2",
    ],
)

# Perform the standard setup call
setuptools.setup(
    name="my_module",
    author="me",
    version="1.2.3",
    license="MIT",
    install_requires=install_requires,
    extras_require=extras_require,
    packages=setuptools.find_packages(),
)

Gotchas

Minor issue with zsh

As mentioned before, when using lazy import errors in import_tracker, if the import error is triggered within a module that is managed as an extras set, the error message is updated to include instructions on which extras set needs to be installed. The error message might look something like this:

ModuleNotFoundError: No module named 'example_module'.

To install the missing dependencies, run `pip install my_module[my_module.example_module]`

There might be an issue when running pip install my_module[my_module.example_module] within a zsh environment, since square brackets in zsh have special meanings. We have to escape them by putting \ (backslash) before them. So for zsh, something like this will work:

pip install my_module\[my_module.example_module\]

Metadata

Release files for import-tracker 3.2.1

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

Built distributions (wheels)

Table of built distributions (wheels) for import-tracker 3.2.1
File
import_tracker-3.2.1-py312-none-any.whl Python 3.12 none any Details
import_tracker-3.2.1-py311-none-any.whl Python 3.11 none any Details
import_tracker-3.2.1-py310-none-any.whl Python 3.10 none any Details
import_tracker-3.2.1-py39-none-any.whl Python 3.9 none any Details
import_tracker-3.2.1-py38-none-any.whl Python 3.8 none any Details
import_tracker-3.2.1-py37-none-any.whl Python 3.7 none any Details

Total release size: 139.1 kB

Release files / import_tracker-3.2.1-py312-none-any.whl

Download URL import_tracker-3.2.1-py312-none-any.whl
Size 23.2 kB
Tags Python 3.12
SHA-256 checksum
How to use checksums
daccbf23fc36265eec0c2d42c94ec1bb074a9bd50fc3143c51d9ef77501e08fb
BLAKE2b-256 checksum
How to use checksums
7b5039394835c556bab01d9bbaf1dee86b4dc9f8170ef5426fbdee0f8668caa9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/5.0.0 CPython/3.12.2

Release files / import_tracker-3.2.1-py311-none-any.whl

Download URL import_tracker-3.2.1-py311-none-any.whl
Size 23.2 kB
Tags Python 3.11
SHA-256 checksum
How to use checksums
3746167218bebf9c595167c7e91e67dcda9c158f7fdff9557c429a89e582bed8
BLAKE2b-256 checksum
How to use checksums
7eb46b1a775882193edc6dc2f6f7f0c87e2e8ccf9c9b98af12e085c91a8a4956
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/5.0.0 CPython/3.11.8

Release files / import_tracker-3.2.1-py310-none-any.whl

Download URL import_tracker-3.2.1-py310-none-any.whl
Size 23.2 kB
Tags Python 3.10
SHA-256 checksum
How to use checksums
3b408c85f3e2da4f77d4c5f4b9d79c1cdc2dd270ecbb213fbd83aef168047b1a
BLAKE2b-256 checksum
How to use checksums
37bbb43bb7f702e616db5ca5beb8f098a4d01145caaaad4c54c856e7263ced95
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/5.0.0 CPython/3.10.13

Release files / import_tracker-3.2.1-py39-none-any.whl

Download URL import_tracker-3.2.1-py39-none-any.whl
Size 23.2 kB
Tags Python 3.9
SHA-256 checksum
How to use checksums
785a8effc9ba4a66ea924233e4f228749b60ca7f8f33776c553a59e51baf3c48
BLAKE2b-256 checksum
How to use checksums
3914f6a25b274aeac8bb43a52ca0817bfb368f050af2e574e1bf16b63d2c6723
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/5.0.0 CPython/3.9.18

Release files / import_tracker-3.2.1-py38-none-any.whl

Download URL import_tracker-3.2.1-py38-none-any.whl
Size 23.2 kB
Tags Python 3.8
SHA-256 checksum
How to use checksums
8a09784c7575448159ba684f8f2a139bb0430f723ad66b2bc29f53ed62985b3d
BLAKE2b-256 checksum
How to use checksums
37f9351a92c4e9c229eb96aa7b165a18cfa3dcf6644dff8566c664ea1e7bc7f8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/5.0.0 CPython/3.8.18

Release files / import_tracker-3.2.1-py37-none-any.whl

Download URL import_tracker-3.2.1-py37-none-any.whl
Size 23.2 kB
Tags Python 3.7
SHA-256 checksum
How to use checksums
f353204e93d720ca030cd91cac022f7af57a1674f26b95b01d42ab9f2174b232
BLAKE2b-256 checksum
How to use checksums
b2214cc19c331cfac18a64a106c819f401930d3353e0db42d55c83fbeda2979c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.7.17

Release history Release notifications | RSS feed

This release

3.2.1 This release

6 release files

3.2.0

4 release files

3.1.5

4 release files

3.1.4

4 release files

3.1.3

4 release files

3.1.2

4 release files

3.1.1

4 release files

3.1.0

4 release files

3.0.0

4 release files

2.2.2

4 release files

2.2.1

4 release files

2.2.0

4 release files

2.1.1

4 release files

2.1.0

4 release files

2.0.3

4 release files

2.0.2

4 release files

2.0.1

4 release files

2.0.0

4 release files

1.4.0

4 release files

1.3.0

4 release files

1.2.0

4 release files

1.1.1

4 release files

1.1.0

4 release files

1.0.2

4 release files

1.0.1

4 release files

1.0.0

4 release files

0.1.0

4 release files

0.0.8

4 release files

0.0.7

4 release files

0.0.6

4 release files

0.0.5

4 release files

0.0.4

4 release files

0.0.3

4 release files

0.0.2

4 release files

0.0.1

4 release files

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