I installed PyInstaller to create executables for my python scripts, and that works fine. I used PyPandoc to create .docx
reports, which also run fine when the normal python files are run, but not from the PyInstaller generated executable. It gives the error:
Traceback (most recent call last):
File "src\flexmodel_postcalc.py", line 295, in postcalculate_everything
File "src\flexmodel_postcalc.py", line 281, in generate_report_docx
File "src\flexmodel_report_docx.py", line 118, in generate_text_useages_docx
File "pypandoc\__init__.py", line 50, in convert
File "pypandoc\__init__.py", line 70, in _convert
File "pypandoc\__init__.py", line 197, in get_pandoc_formats
File "pypandoc\__init__.py", line 336, in _ensure_pandoc_path
OSError: No pandoc was found: either install pandoc and add it
to your PATH or install pypandoc wheels with included pandoc.
During the executable creation I see no strange issues about PyPandoc. How can I include Pandoc into my executable so others (without Python and/or Pandoc installation) can use the executable and create .docx
reports?
edit: a working process included the following steps:
Create a file including the following code:
import pypandoc
pypandoc.convert(source='# Sample title\nPlaceholder', to='docx', format='md', outputfile='test.docx')
Save this file as pythonfile.py
create an executable with PyInstaller:
pyinstaller --onefile --clean pythonfile.py
Now the executable should run on a computer without Pandoc (or PyPandoc) installed.
There are two issues here. The first one is that pypandoc
needs pandoc.exe
to work. This is not picked up by pyinstaller
automatically, but you can specify it manually.
To do this you you have to create a .spec
file. The one I generated and used looks like this:
block_cipher = None
a = Analysis(['pythonfile.py'],
pathex=['CodeDIR'],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='EXEName',
debug=False,
strip=False,
upx=True,
console=True ,
resources=['YourPandocLocationHere\\\\pandoc.exe'])
You can build the executable by using pyinstaller myspec.spec
. Don't forget to change the paths and the name
parameter.
If you were building that in a directory mode this should be enough. However, for the one-file
mode, things are a bit more complicated due to the way the pyinstaller bootloader process works. The pandoc.exe
file is unzipped during execution in a temporary folder, but the execution happens in your original .exe
folder. According to this question, you have to add the following lines to your code before calling pypandoc to change your current folder, if you run the frozen code.
if hasattr(sys, '_MEIPASS'):
os.chdir(sys._MEIPASS)