2025, Oct 22 08:03
Как исправить ошибку No module named matplotlib при сборке PyInstaller с PyQt6
Почему PyInstaller не включает matplotlib: ошибка No module named matplotlib при сборке .exe для PyQt6 на Windows и как решить её установкой зависимости.
Упаковка небольшого настольного приложения на PyQt6 в один исполняемый файл для Windows нередко спотыкается о на удивление простую проблему: отсутствующую зависимость на этапе сборки. Даже если прописать скрытые импорты и флаги collect-all, PyInstaller не сможет включить библиотеки, которых нет в текущем окружении. Итог — ошибка при запуске с понятным сообщением: No module named matplotlib.
Как воспроизвести окружение и сбой сборки
Приложение собирается в единый .exe с PyInstaller и следующими зависимостями:
PyQt6==6.9.1
PyQt6-Qt6==6.9.1
PyQt6_sip==13.10.2
qt-material==2.17
pyinstaller==6.14.2
В файле spec для PyInstaller добавлены скрытые импорты для matplotlib и его бэкендов:
# -*- mode: python ; coding: utf-8 -*-
graph = Analysis(
    ['DSS.py'],
    pathex=[],
    binaries=[],
    datas=[],
    hiddenimports=['matplotlib', 'matplotlib.backends.backend_tkagg', 'matplotlib.backends.backend_pdf'],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=['PyQt5'],
    noarchive=False,
    optimize=0,
)
archive = PYZ(graph.pure)
app_exe = EXE(
    archive,
    graph.scripts,
    graph.binaries,
    graph.datas,
    [],
    name='DNA_Sequence_Similarities',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
    icon=['icon.ico'],
)
bundle_collect = COLLECT(
    app_exe,
    graph.binaries,
    graph.zipfiles,
    graph.datas,
    strip=False,
    upx=True,
    upx_exclude=[],
    name='DNA_Sequence_Similarities',
)
Команда сборки дополнительно указывает скрытые импорты и пытается собрать пакеты:
pyinstaller DSS.py 
  --name DNA_Sequence_Similarities 
  --onefile 
  --windowed 
  --icon=icon.ico 
  --hidden-import=matplotlib 
  --hidden-import=matplotlib.backends.backend_tkagg 
  --hidden-import=matplotlib.backends.backend_pdf 
  --collect-all matplotlib 
  --collect-all qt_material 
  --collect-all PyQt6
Несмотря на это, исполняемый файл на целевых машинах падает с No module named matplotlib. Лог сборки подтверждает проблему: Hidden import 'matplotlib.backends.backend_tkagg' not found и Hidden import 'matplotlib.backends.backend_pdf' not found.
В чём реальная причина
PyInstaller анализирует текущее окружение Python и «замораживает» только те импорты, которые удаётся разрешить. Если библиотека не установлена на момент сборки, включать попросту нечего. В показанной конфигурации matplotlib отсутствует в списке зависимостей и, следовательно, не установлен в окружении сборки. Поэтому флаги hidden-import не срабатывают: PyInstaller не может найти модули, которых локально нет.
Во время выполнения сообщение максимально прямое, а на этапе анализа повторяется то же самое: скрытые импорты бэкендов matplotlib обнаружить не удаётся.
Решение
Установите matplotlib в окружение сборки и добавьте его в зависимости проекта. Как только библиотека появится, текущий spec и настройки hidden-import позволят PyInstaller найти и упаковать её вместе с исполняемым файлом.
pip install matplotlib
В итоге набор зависимостей будет таким:
PyQt6==6.9.1
PyQt6-Qt6==6.9.1
PyQt6_sip==13.10.2
qt-material==2.17
pyinstaller==6.14.2
matplotlib
Пересоберите приложение той же командой — в исполняемый файл попадёт matplotlib. Предыдущие ошибки лога о недостающих бэкендах matplotlib исчезнут, как только пакет будет доступен.
Почему это важно
При поставке автономного десктопного приложения любой импорт, выполняемый во время работы, должен присутствовать в окружении уже на этапе сборки. Иначе PyInstaller не сможет его «заморозить», и финальный бинарник упадёт на машинах без установленной зависимости. Это особенно критично для GUI-стеков вроде PyQt6, которые часто интегрируются с библиотеками визуализации. Сборка должна быть самодостаточной, а начинается это с полного списка зависимостей.
Стоит прислушиваться и к сообщениям, которые выдаёт сборка. Например, в логе отмечено, что qt_material следует импортировать после PySide или PyQt. Подобные подсказки помогают заранее проверить порядок импортов и ожидания упаковки ещё до распространения.
Выводы
Держите окружение сборки в соответствии с реальными импортами приложения, убедитесь, что все нужные библиотеки перечислены и установлены — дальше PyInstaller справится сам. Если в логе появляется сообщение, что скрытый импорт не найден, самый прямой путь к решению — сделать модуль доступным в окружении, как показано на примере с matplotlib.
Статья основана на вопросе на StackOverflow от Maifee Ul Asad и ответе Pratik Pathak.