I'm having problems with PyInstaller and statsmodels
. When I run the executable I got the error ImportError: No module named 'statsmodels.__init__.tools'
, when I run the code directly with Python everything works normally.
I have tried this solution.
It works for the tools
module, but I got another error:
I have try to add the statsmodels
,statsmodels.__init__
and statsmodels.__init__._version
, but it didn't work either.
statsmodels
is one of the complex modules for PyInstaller and that is because it depends on some other modules that they would mess the PyInstaller import graph. My solution might not look optimized but would do the job.
hidden-imports
would only tell PyInstaller to look for that module but sometimes it can't trace module dependencies (like DLLs, external py files, etc.). so for statsmodels
it won't help.
The overall procedure is to first tell PyInstaller to don't trace statsmodels
with exclude-module
and feed the module manually to the final executable.
Also, we need to bundle some modules like (numpy
, pandas
, etc) with Tree
class.
I'm using Python 3.7.4 with latest PyInstaller 3.5. Suppose below example taken from official docs.
import numpy as np
import statsmodels.api as sm
import statsmodels.formula.api as smf
dat = sm.datasets.get_rdataset("Guerry", "HistData").data
results = smf.ols('Lottery ~ Literacy + np.log(Pop1831)', data=dat).fit()
print(results.summary())
Use below spec file (I'm using Python's venv called env
next to the script)
# -*- mode: python -*-
block_cipher = None
a = Analysis(['script.py'],
pathex=['<root_project_path>'],
binaries=[],
datas=[],
hiddenimports=['six', 'fractions', 'csv', 'pytz', 'timeit'],
hookspath=[],
runtime_hooks=[],
excludes=['statsmodels'],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
a.datas += Tree("./env/Lib/site-packages/statsmodels", prefix="statsmodels")
a.datas += Tree("./env/Lib/site-packages/numpy", prefix="numpy")
a.datas += Tree("./env/Lib/site-packages/pandas", prefix="pandas")
a.datas += Tree("./env/Lib/site-packages/scipy", prefix="scipy")
a.datas += Tree("./env/Lib/site-packages/dateutil", prefix="dateutil")
a.datas += Tree("./env/Lib/site-packages/patsy", prefix="patsy")
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='script',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=False,
runtime_tmpdir=None,
console=True )
And finally generate your executable with:
pyinstaller script.spec
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With