Pyinstaller: Module not found when running .exe when generated with --hidden-import

35,587 views
Skip to first unread message

Clive Bostock

unread,
Aug 13, 2020, 6:13:18 AM8/13/20
to PyInstaller
I have a problem which I have reduced to a small program. The program tries to write a Pandas dataframe.

This works find in PyCharm, but when I produce a Windows exe using PyInstaller it errors at runtime:


.\pyinst_excel.exe
Traceback (most recent call last):
  File "pyinst_excel.py", line 31, in <module>
  File "pyinst_excel.py", line 25, in add_generated_files_row
  File "site-packages\pandas\io\excel\_openpyxl.py", line 18, in __init__
ModuleNotFoundError: No module named 'openpyxl'
[11408] Failed to execute script pyinst_excel

I have tried explicitly importing openpyxl and that didn't work and I have also used --hidden-import:

call venv\Scripts\activate pyinstaller --onefile --hidden-import _openpyxl --hidden-import openpyxl --clean pyinst_excel.py

The generated spec file looks like this:

# -*- mode: python ; coding: utf-8 -*- block_cipher = None a = Analysis(['pyinst_excel.py'], pathex=['D:\\Development\\OEM-SR-Rules'], binaries=[], datas=[], hiddenimports=['_openpyxl', 'openpyxl'], hookspath=[], runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE(pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], name='pyinst_excel', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=True )

However this doesn't fix the problem. From the build/warnings file I see:

... missing module named openpyxl - imported by pandas.io.excel._openpyxl (delayed, conditional), D:\Development\OEM-SR-Rules\pyinst_excel.py (top-level) ... missing module named 'openpyxl.styles' - imported by pandas.io.excel._openpyxl (delayed) missing module named 'openpyxl.style' - imported by pandas.io.excel._openpyxl (delayed)

Program code:

import argparse from operator import attrgetter import os import sys import json import pandas as pd import numpy as np from pathlib import Path import glob import re import time from sys import exit from shutil import copyfile REPORT_DATE_FMT = '%d-%m-%Y %H.%M' def add_generated_files_row(generated_excel, sequence: int, date_generated): # gen_files_df = pd.read_excel(generated_files_excel, index_col=0) gen_files_df = pd.DataFrame(columns=['Sequence', 'Date Generated']) new_row = {'Sequence': sequence, 'Date Generated': date_generated} gen_files_df = gen_files_df.append(new_row, ignore_index=True, sort=False) writer = pd.ExcelWriter(generated_excel) gen_files_df.to_excel(writer) generated_files_excel = Path('D:\temp\test.xlsx') date_generated = time.strftime(f"{REPORT_DATE_FMT}") add_generated_files_row(generated_files_excel, 1, date_generated)

I am using Windows10, Python 3.8 and PyInstaller 3.6. Having read that Pyinstaller is not supported under 3.8, I also reproduced the problem with Python 3.7.6.

I am out of ideas. Any help would be much appreciated.


Thanks,


Clive


bwoodsend

unread,
Aug 13, 2020, 8:53:03 AM8/13/20
to PyInstaller

Do you have openpyxl installed (i.e. does import openpyxl work normally)? Pandas tries a range of backends to read and write xlsx files - you need to ensure that the one you tell PyInstaller to include is the one that you actually have. For reading it’s usually xlrd and writing either xlsxwriter or xlwt. Whichever one(s) you have you should mark as hidden imports.

If that isn’t the problem then navigate to build/pyinst_excel/xref-pyinst_excel.html and find openpyxl in it. It should say if it could find it and why it didn’t include it there.

Brénainn

cbost...@gmail.com

unread,
Aug 17, 2020, 5:51:29 AM8/17/20
to PyInstaller
Hi Brénainn.

Yes,  it is installed via PyCharm under my venv. If I execute from within PyCharm it runs fine and if I set my environment in a Windows command shell it also works fine:

D:\Development\Python\Experimental\Pyinstaller>call venv\Scripts\activate

(venv) D:\Development\Python\Experimental\Pyinstaller>python pyinst_excel.py
                                                                                                                                                          <= Silently executes -  no error
(venv) D:\Development\Python\Experimental\Pyinstaller>dist\pyinst_excel.exe

Traceback (most recent call last):
  File "pyinst_excel.py", line 31, in <module>
    add_generated_files_row(generated_files_excel, 1, date_generated)

  File "pyinst_excel.py", line 25, in add_generated_files_row
    writer = pd.ExcelWriter(generated_excel)

  File "site-packages\pandas\io\excel\_openpyxl.py", line 18, in __init__
ModuleNotFoundError: No module named 'openpyxl'
[15952] Failed to execute script pyinst_excel                                                                          <= Executed after re-generating with pyinstaller command below


I am using a BAT file to generate the executable, which ensures that my virtual environment is set when I generate:

call venv\Scripts\activate
pyinstaller  --onefile --hidden-import _openpyxl --hidden-import xlsxwriter --hidden-import openpyxl --hidden-import xlwt  --clean  pyinst_excel.py

The xref-pyinst_excel.html file includes:


'openpyxl.style' MissingModule

'openpyxl.styles' MissingModule
...
xlwt MissingModule

In total, there are roughly 50 missing modules shown in the html file. I have just listed the ones which are immediately relevant.

Thanks,

Clive

bwoodsend

unread,
Aug 17, 2020, 7:59:19 AM8/17/20
to PyInstaller

Hi,

I am using a BAT file to generate the executable

Grr, why does everyone instantly go for this. The spec file contains all your input parameters. Once you’ve called pyinstaller --onefile --hidden-import _openpyxl --hidden-import xlsxwriter --hidden-import openpyxl --hidden-import xlwt --clean pyinst_excel.py once, in future you can just call PyInstaller pyinst_excel.spec.

But that doesn’t matter - it should still work.

openpyxl.style' MissingModule
imported by: pandas.io.excel._openpyxl

'openpyxl.styles' MissingModule
imported by: pandas.io.excel._openpyxl

This tells us that PyInstaller is aware of the openpyxl dependencies (even before we explicitly told it with the --hidden-imports) but can’t find them. This usually boils down to venvs getting mixed up. Could you run it as python -m PyInstaller [rest of the command here]?

Brénainn

Message has been deleted

bwoodsend

unread,
Aug 17, 2020, 4:44:43 PM8/17/20
to PyInstaller

If python -m PyInstaller gives a No module named PyInstaller error then your venv is a mess and PyInstaller is not in the correct environment. Using python -m ... forces it to use the correct PyInstaller (which doesn’t exist). The PyInstaller in your PATH presumably is left over from some other old environment (use where PyInstaller to find out which) or your root environment.

The fix is just to install PyInstaller in your venv using:

venv\Scripts\activate
pip install PyInstaller

Verify that the 1st (or only) output from where PyInstaller now points inside your venv/Scripts.

cbost...@gmail.com

unread,
Aug 18, 2020, 5:03:06 AM8/18/20
to PyInstaller
Fantastic - that did the trick:

(venv) D:\Development\OEM-SR-Rules>pip install PyInstaller
Requirement already satisfied: PyInstaller in d:\development\oem-sr-rules\venv\lib\site-packages (4.0)
Requirement already satisfied: pyinstaller-hooks-contrib>=2020.6 in d:\development\oem-sr-rules\venv\lib\site-packages (from PyInstaller) (2020.7)
Requirement already satisfied: pywin32-ctypes>=0.2.0; sys_platform == "win32" in d:\development\oem-sr-rules\venv\lib\site-packages (from PyInstaller) (0.2.0)
Requirement already satisfied: pefile>=2017.8.1; sys_platform == "win32" in d:\development\oem-sr-rules\venv\lib\site-packages (from PyInstaller) (2019.4.18)
Requirement already satisfied: setuptools in d:\development\oem-sr-rules\venv\lib\site-packages (from PyInstaller) (49.2.0)
Requirement already satisfied: altgraph in d:\development\oem-sr-rules\venv\lib\site-packages (from PyInstaller) (0.17)
Requirement already satisfied: future in d:\development\oem-sr-rules\venv\lib\site-packages (from pefile>=2017.8.1; sys_platform == "win32"->PyInstaller) (0.18.2)
WARNING: You are using pip version 20.1.1; however, version 20.2.2 is available.
You should consider upgrading via the 'd:\development\oem-sr-rules\venv\scripts\python.exe -m pip install --upgrade pip' command.

(venv) D:\Development\OEM-SR-Rules>where PyInstaller
D:\Development\OEM-SR-Rules\venv\Scripts\pyinstaller.exe
C:\Users\CBOSTOCK\AppData\Local\Programs\Python\Python38\Scripts\pyinstaller.exe

I regenerated the EXE and then:

(venv) D:\Development\OEM-SR-Rules>dist\pyinst_excel.exe

(venv) D:\Development\OEM-SR-Rules>                                    
<= No errors

I also tested my original program and that works too!

One final question, if I may. I wish to go back to using the spec file. However I am unsure as to how PyInstaller manages it. According to the docs, the first thing it does is write the spec file. Do I have to use a non default name (with "--specpath=" ) to stop it overwriting my spec file or does it not overwrite it if it finds it is already there?

Thanks,

Clive

bwoodsend

unread,
Aug 18, 2020, 5:33:37 AM8/18/20
to PyInstaller

Under the hood PyInstaller always uses a spec file. If you use PyInstaller --[some options] script.py it will generate script.spec (overwriting it if one already exists) that contains all your options, then call automatically PyInstaller script.spec.

If you want to use the spec to avoid having to list all your options every time (strongly recommended) then just call PyInstaller script.spec which will run it without modifying it. If you want to change your options then you modify the spec (it’s just a Python script).

cbost...@gmail.com

unread,
Aug 18, 2020, 5:52:29 AM8/18/20
to PyInstaller
Thanks for you help Brénainn - very much appreciated.

cbost...@gmail.com

unread,
Aug 18, 2020, 7:18:17 AM8/18/20
to PyInstaller
Extra bonus - not only did fixing the venv get rid or the error, but the "--hidden-import" option(s) no longer required. :o)

On Tuesday, 18 August 2020 at 10:33:37 UTC+1 bwoodsend wrote:

Tomasz Mazowiecki

unread,
Dec 12, 2021, 1:11:46 PM12/12/21
to PyInstaller
Hello. Got similar problem with pyinstaller. I made a small gui program that opens exe file using openpyxl and does some other stuff with that data but I can't get it to work with exe.
Already tried that solution from above. It works when I create new projekt with new environment in pycharm, then install pyinstaller in that but when I tried on my project, it's not working. Then I tried to make new py file in current project, that only imports openpyxl and same result.
when trying 
(venv) PycharmProjects\adnoc_file_compare>PyInstaller test_imoprts.py
it ends with 
Unable to find "pycharmprojects\adnoc_file_compare\venv\lib\site-packages\setuptools-28.8.0-py3.6.egg\EGG-INFO" when adding binary and data files.

Tomasz Mazowiecki

unread,
Dec 13, 2021, 9:07:14 AM12/13/21
to PyInstaller
I solved it with a workaround. Since it worked in fresh environment, I created a separate exe with that, to get data from excel and print out. Then in main program i used subprocess to run that excel.exe to get data, converted it to string and modified to convert it into other types I needed. Now I got problem with Oracle library, but that's for probably different topic.
Reply all
Reply to author
Forward
0 new messages