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.
$ 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.
pip install --target ./vendor -r requirements.txt
PYTHONPATH=./vendor python -c "import requests; print(requests.__version__)"Persist PYTHONPATH across steps in CI
- run: pip install --target ./vendor -r requirements.txt
- run: echo "PYTHONPATH=$PWD/vendor" >> "$GITHUB_ENV"
- run: python app.py # now finds vendored packagesPrefer 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
--targetfor bundling; setPYTHONPATHwherever that code runs. - Use
$GITHUB_ENVto persistPYTHONPATHacross steps. - Use a venv when you just need importable dependencies.