PyInstaller ModuleNotFoundError: No module named (tested)
If python app.py works but the PyInstaller exe fails with ModuleNotFoundError: No module named ..., either the module is imported dynamically (add --hidden-import name) or pyinstaller ran from a different environment than your packages (install it in your venv and run python -m PyInstaller).
1. A dynamic import PyInstaller cannot see
app.py (PyInstaller 6.22.3, Python 3.13.5, Linux):
import importlib
name = "colorsys"
mod = importlib.import_module(name) # PyInstaller cannot see this import
print(mod.rgb_to_hsv(1, 0, 0))
Built and run (each pyinstaller command was run with --log-level WARN and its last 3 lines kept, so successful builds print nothing here):
$ pyinstaller --onefile app.py
$ ./dist/app
Traceback (most recent call last):
File "app.py", line 3, in <module>
mod = importlib.import_module(name) # PyInstaller cannot see this import
File "importlib/__init__.py", line 88, in import_module
File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
File "<frozen importlib._bootstrap>", line 1324, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'colorsys'
[PYI-3373348:ERROR] Failed to execute script 'app' due to unhandled exception!
exit=1
Then the same script with plain Python, and rebuilt with --hidden-import:
$ python app.py
(0.0, 1.0, 1)
$ pyinstaller --onefile --hidden-import colorsys app.py && ./dist/app
(0.0, 1.0, 1)
exit=0
PyInstaller finds modules by reading your import statements at build time. A module imported by a string at run time (importlib.import_module(name), __import__, plugin loaders, some libraries' lazy imports) is not collected, so the bundle has no copy and the exe fails with ModuleNotFoundError: No module named ..., even though python app.py works. --hidden-import colorsys (or hiddenimports=[...] in the .spec file) adds it. For a package with many submodules, --collect-submodules pkg adds them all.
2. PyInstaller from a different environment than your packages
app2.py is from tabulate import tabulate plus one print. tabulate is installed only in the project venv proj; the pyinstaller command used first belongs to another environment:
$ proj/bin/python app2.py # tabulate is installed in the project venv
name n
------ ---
a 1
$ /tmp/fx384/ve/bin/pyinstaller --onefile app2.py # pyinstaller from ANOTHER environment
$ ./dist/app2
ModuleNotFoundError: No module named 'tabulate'
[PYI-3374518:ERROR] Failed to execute script 'app2' due to unhandled exception!
$ uv pip install -p proj/bin/python pyinstaller && proj/bin/python -m PyInstaller --onefile app2.py
150 INFO: Platform: Linux-6.12.107+deb13-amd64-x86_64-with-glibc2.41
150 INFO: Python environment: /tmp/pi403/proj
150 INFO: wrote /tmp/pi403/app2.spec
$ ./dist/app2
name n
------ ---
a 1
PyInstaller bundles what its own Python can import. A pyinstaller installed globally, with pipx, or in another venv does not see the packages in your project venv, and the build still produces an exe that fails at start. Install PyInstaller into the same environment as your dependencies and run it as python -m PyInstaller with that environment's Python; the build log line Python environment: confirms which one was used.
Checklist when the exe says No module named X: does python -c "import X" work with the same Python that runs PyInstaller? Is X imported by a string? Then --hidden-import X. Rebuild with --clean after changing the environment.
Related: PyInstaller error: unrecognized arguments ยท uv pip install -r requirements.txt.
Frequently asked questions
Why does my PyInstaller exe say No module named but python works?
PyInstaller only bundles modules it finds in import statements, using its own Python environment. Dynamic imports and packages installed in a different venv are left out.
How do I add a hidden import in PyInstaller?
pyinstaller --hidden-import modname app.py, or hiddenimports=["modname"] in the .spec file; --collect-submodules pkg adds every submodule of a package.
Which Python does PyInstaller use?
The one it is installed in. Install it into your project venv and run python -m PyInstaller; the build log line "Python environment:" shows which environment was used.
Written with AI assistance. Measured on 2026-10-23 with PyInstaller 6.22.3, Python 3.13.5 and uv 0.13.5 on Linux. Each command was run verbatim and the output pasted unedited (pyinstaller run with --log-level WARN and trimmed with tail, as stated). PlainTables is our extension; PyInstaller is free.