Skip to content
Latchkey

pip "--target" Directory Not Importable at Runtime in CI

Installing with pip install --target DIR puts packages in DIR but does not add DIR to sys.path. A later step that does not set PYTHONPATH runs the bare interpreter, which cannot find them.

What this error means

A --target install succeeds, then a subsequent step fails with ModuleNotFoundError for a package you clearly installed. Setting PYTHONPATH=DIR for that step makes it import, proving the location was simply off the path.

CI log
$ pip install --target ./vendor requests   # OK
$ python -c "import requests"
ModuleNotFoundError: No module named 'requests'

Common causes

--target does not modify sys.path

Unlike a venv or a normal site install, --target only copies files into DIR. Nothing registers DIR as an import root, so the default interpreter ignores it.

PYTHONPATH not set in the running step

Each CI step is a fresh shell. If the step that runs your code does not export PYTHONPATH=DIR, the target directory is invisible to imports.

How to fix it

Put the target directory on PYTHONPATH

Export PYTHONPATH so the interpreter searches the target dir.

Terminal
pip install --target ./vendor -r requirements.txt
PYTHONPATH=./vendor python -c "import requests; print(requests.__version__)"

Persist PYTHONPATH across steps in CI

.github/workflows/ci.yml
- run: pip install --target ./vendor -r requirements.txt
- run: echo "PYTHONPATH=$PWD/vendor" >> "$GITHUB_ENV"
- run: python app.py   # now finds vendored packages

Prefer a venv when you do not need a flat dir

--target is for bundling (Lambda layers, zipapps). For ordinary CI, a venv puts packages on the path automatically.

How to prevent it

  • Reserve --target for bundling; set PYTHONPATH wherever that code runs.
  • Use $GITHUB_ENV to persist PYTHONPATH across steps.
  • Use a venv when you just need importable dependencies.

Frequently asked questions

What causes "--target not on path"?
Unlike a venv or a normal site install, --target only copies files into DIR. Nothing registers DIR as an import root, so the default interpreter ignores it.
How do I fix --target not on path?
Export PYTHONPATH so the interpreter searches the target dir.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card