Fixing "ModuleNotFoundError No module named PyQt6" when packaging with PyInstaller

Why PyInstaller can't find PyQt6 and how to fix it
Heads up! You've already completed this tutorial.

I'm having a problem when opening my packaged .exe — I get ModuleNotFoundError: No module named 'PyQt6' followed by Failed to execute script. What am I doing wrong?

This is one of the most common issues people run into when packaging PyQt6 applications with PyInstaller. You write your app, it works perfectly when you run it with Python, but as soon as you package it into an .exe and try to open it — a ModuleNotFoundError crashes the whole thing.

The good news is that this almost always comes down to your Python environment, and the fix is usually straightforward.

Why this happens

When PyInstaller builds your application, it analyzes your Python script to figure out which packages and modules your code depends on. It then bundles those modules into the final executable.

If PyInstaller can't find PyQt6 in the environment it's running from, it won't include it in the bundle. When someone (including you) then tries to run the .exe, Python inside the bundled app looks for PyQt6, can't find it, and throws the ModuleNotFoundError.

There are a few common reasons PyInstaller might fail to discover PyQt6:

  1. You're running PyInstaller from the wrong environment. PyQt6 is installed in one place, but PyInstaller is running from another.
  2. Conda environments can cause discovery issues. Anaconda and Miniconda manage packages differently from plain pip, and PyInstaller sometimes struggles to find packages installed through conda.
  3. PyQt6 is installed, but in a way PyInstaller can't detect. This can happen with unusual installation methods or broken package metadata.

Use a clean virtual environment with pip

The most reliable way to fix this is to create a fresh virtual environment, install everything with pip, and run PyInstaller from within that environment. This ensures that PyInstaller and your application dependencies are all in the same place, and that package metadata is in the format PyInstaller expects.

Here's how to set this up from scratch.

Create a virtual environment

Open a terminal and navigate to your project folder, then create a new virtual environment:

sh
python -m venv packenv

Activate it:

  • Windows: sh packenv\Scripts\activate

  • macOS / Linux: sh source packenv/bin/activate

You should see (packenv) at the beginning of your terminal prompt, confirming you're inside the environment.

Install your dependencies

Now install PyQt6 and PyInstaller into this environment using pip:

sh
pip install PyQt6 pyinstaller

If your project uses other packages, install those too. You can use a requirements.txt file if you have one:

sh
pip install -r requirements.txt

Run PyInstaller from the activated environment

With the virtual environment still active, run PyInstaller against your script:

sh
pyinstaller --windowed main.py

Replace main.py with the name of your entry-point script. The --windowed flag prevents a console window from appearing alongside your GUI app (on Windows).

Because PyInstaller is now running inside the same environment where PyQt6 is installed via pip, it will correctly discover and bundle the PyQt6 modules.

If you were using Anaconda

If you originally installed PyQt6 (or PyQt6) through conda, this is very likely the source of the problem. Conda installs packages in a different directory structure and uses different metadata formats than pip. PyInstaller is designed primarily around pip-installed packages, so it can fail to detect conda-installed packages.

The fix, as described above, is to switch to a plain pip-based virtual environment for packaging. You don't have to abandon Anaconda for your day-to-day development — just use a separate pip environment when it's time to package your app.

Verify that it works before packaging

Before running PyInstaller, it's worth confirming that your script runs correctly inside the virtual environment. With the environment activated:

sh
python main.py

If your application launches normally, you know all the dependencies are present. If it fails here, the issue is with your environment setup rather than with PyInstaller.

Dealing with hidden imports

Even with the environment set up correctly, you might occasionally see warnings about missing modules during the PyInstaller build. Many of these warnings are harmless — they relate to optional modules that your application doesn't actually use.

However, if your packaged app fails at runtime with a ModuleNotFoundError for a specific module (not PyQt6 itself), you may need to tell PyInstaller about it explicitly using the --hidden-import flag:

sh
pyinstaller --windowed --hidden-import=some_module main.py

For PyQt6 applications, the most common hidden imports you might need are submodules like PyQt6.sip:

sh
pyinstaller --windowed --hidden-import=PyQt6.sip main.py

You can also add multiple hidden imports:

sh
pyinstaller --windowed --hidden-import=PyQt6.sip --hidden-import=PyQt6.QtPrintSupport main.py

Using a .spec file

After your first PyInstaller run, you'll find a .spec file in your project directory (e.g., main.spec). This file controls how PyInstaller builds your application, and you can edit it directly to add hidden imports or other configuration.

Open the .spec file and look for the hiddenimports list inside the Analysis block:

python
a = Analysis(
    ['main.py'],
    pathex=[],
    binaries=[],
    datas=[],
    hiddenimports=['PyQt6.sip'],  # Add any missing modules here
    hookspath=[],
    ...
)

Then build using the .spec file instead of your script:

sh
pyinstaller main.spec

This gives you a repeatable, version-controllable build configuration.

A complete example

Here's a minimal PyQt6 application that you can use to test your packaging setup. If you're new to PyQt6, see our tutorial on creating your first window for a more detailed walkthrough.

python
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Packaging Test")
        label = QLabel("Hello! If you can see this, packaging worked.")
        label.setMargin(20)
        self.setCentralWidget(label)


app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

Save this as main.py, then from your activated virtual environment:

sh
pip install PyQt6 pyinstaller
pyinstaller --windowed main.py

Your packaged application will be in the dist/main/ folder. Run the executable from there and you should see the window appear without any ModuleNotFoundError.

For a complete guide to packaging PyQt6 apps on Windows — including creating an installer — see our packaging PyQt6 applications with PyInstaller on Windows tutorial.

Quick checklist

If you hit this error, work through these steps:

  • Create a fresh virtual environment using python -m venv.
  • Install everything with pip, not conda.
  • Activate the environment before running PyInstaller.
  • Test your script inside the environment before packaging.
  • Add hidden imports if specific modules are still missing at runtime.

Following these steps resolves the issue in the vast majority of cases. The underlying cause is almost always a mismatch between where PyInstaller is looking for packages and where they're actually installed — and a clean pip environment eliminates that mismatch entirely.

If you're packaging for macOS instead, take a look at our guide to packaging PyQt6 applications as a macOS DMG.

Well done, you've finished this tutorial! Mark As Complete
[[ user.completed.length ]] completed [[ user.streak+1 ]] day streak

Bring Your PyQt/PySide Application to Market

Stuck in development hell? I'll help you get your project focused, finished and released. Benefit from years of practical experience releasing software with Python.

Find out More

Martin Fitzpatrick

Fixing "ModuleNotFoundError No module named PyQt6" when packaging with PyInstaller was written by Martin Fitzpatrick.

Martin Fitzpatrick has been developing Python/Qt apps for 8 years. Building desktop applications to make data-analysis tools more user-friendly, Python was the obvious choice. Starting with Tk, later moving to wxWidgets and finally adopting PyQt. Martin founded PythonGUIs to provide easy to follow GUI programming tutorials to the Python community. He has written a number of popular Python books on the subject.