python-openxml / python-docx

Create and modify Word documents with Python
MIT License
4.55k stars 1.12k forks source link

Pyinstall fails #289

Closed sssseossss closed 8 years ago

sssseossss commented 8 years ago

Hi! I'm trying to compile the program into exe with pyinstall. When I run the program, I get the error that default.docx is not found. Is there any way I can resolve this? Many thanks!!!

Error is below:

Traceback (most recent call last): File "", line 1344, in File "", line 952, in menu File "", line 1291, in generate_report File "site-packages\docxtplinit.py", line 116, in new_subdoc File "site-packages\docxtplinit.py", line 123, in init File "site-packages\docx\api.py", line 25, in Document File "site-packages\docx\opc\package.py", line 116, in open File "site-packages\docx\opc\pkgreader.py", line 32, in from_file File "site-packages\docx\opc\phys_pkg.py", line 31, in new docx.opc.exceptions.PackageNotFoundError: Package not found at 'C:\Users\sp\AppData\Local\Temp_MEI48882\docx\templates\default.docx'

scanny commented 8 years ago

This has to do with the default .docx document "data" file not being stored by PyInstaller.

If you search on "PyInstaller data files" I think you'll find some information on this.

Also, if you always use your own template files, i.e. `document = Document('some-file.docx') I think the error is avoided.

thebeancounter commented 7 years ago

@scanny i am getting somthing similar with pyinstaller and python-pptx is there any way to get pyinstaller to include that default pptx template?

pptx.exc.packagenotfounderror: package not found at ....\default.pptx

thanks!

sssseossss commented 7 years ago

Hi, just to make your life easier, this is how I resolved it: edit the file in Python3.5\LIB\site-packages\docx\api.py in the function _default_docx_path amend the link to your empty docx file. In my example: the last line of this function "return" line I replaced _thisdir variable to my script directory so it looked like this: return os.path.join('c:\program\\','bin','default.docx') good luck...

thebeancounter commented 7 years ago

@sssseossss thanks! will that put the default file in bundled with the exe? i don't want the end user to have to worry about that

sssseossss commented 7 years ago

No, you have to put that empty file... thats how the module works, unfortunately :)

thebeancounter commented 7 years ago

@sssseossss i have to put it before the compilation and than it will bundle it to the exe, or it has to be present in every computer that runs the exe and in the same path?

sssseossss commented 7 years ago

Put before installation and then carry as a separate file with exe...

scanny commented 7 years ago

@thebeancounter This is really a PyInstaller question, and I don't have any expertise with that because I never use it.

This section in the PyInstaller documentation looks like it may have some clues:
https://pythonhosted.org/PyInstaller/spec-files.html#adding-data-files

The default template .docx is at the path './templates/default.docx' relative to the root docx module. Depending on how PyInstaller interprets paths, you might need to add 'docx/' before 'templates/'.

Let us know when you figure it out so others can find it on search. That's another form of contributing to the project :)

thebeancounter commented 7 years ago

@scanny i'll give it a try. thanks Scanny, awesome module, helped me a lot!
please note, pyinstaller issue that i opened for this.

sjkelly commented 7 years ago

The following works well for me in the pyinstaller .spec file, and is slightly more generic than the aforementioned solutions. This is a snippet with the relevant line being the datas= line in the Analysis constructor.

import sys
from os import path
site_packages = next(p for p in sys.path if 'site-packages' in p)

a = Analysis([''],
             pathex=[''],
             binaries=[],
             datas=[(path.join(site_packages,"docx","templates"), "docx/templates")],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)
htgoebel commented 6 years ago

@sjkelly What about providing a hook for PyInstaller. Please use collect_data_files(), as you can seen in other hooks.

muzafferkadir commented 6 years ago

i added python\lib\sitepackages\pptx to in project.

parthjpandya commented 5 years ago

I have resolved the issue this way: Getting error because of (1) space in the filename and (2) path. might help someone.

gh421 commented 2 years ago

Just wanted to know if this docx hook has been added to pyinstaller build since 2018, because I am experiencing a similar issue. Also do you have a hook for docx-mailmerge as well or will the hook-docx work with docx-mailmerge?

Pyinstaller creates the package properly with all the other modules, but the exe fails when the pyhon code includes both of these. Nothing to do with a path to a docx file (or docx not found) just doesn't seem to include these modules/libraries in the build.

from mailmerge import MailMerge
from docx import Document

and using aspose.words in the python code instead of these two modules, crashes the exe that pyinstaller creates. Pyinstaller works a treat if you don't want to use the program with docx files. Any chance on getting it fixed? It's not importing the lxml.tree correctly either, which is a part of these two modules. That could be where the fault lies.

htgoebel commented 2 years ago

The best solution would be to provide (and maintain) the hook together with this package. This is very easy, See https://pyinstaller.readthedocs.io/en/stable/hooks.html#providing-pyinstaller-hooks-with-your-package for all required information.