0

I've a Python file titled my_python_file.py that makes, among other things, a .doc file using the python-docx module. The .doc is created perfectly and gives no problem. The problem comes when I build a .exe of my script and I try to make the .doc. An AssertionError problem appears.

This is my exe maker code (exe_maker.py):

from distutils.core import setup
import py2exe, sys, os
sys.argv.append('py2exe')

setup(
    options = {'py2exe': {'bundle_files': 3, 'compressed': True, 'includes': ['lxml.etree', 'lxml._elementpath', 'gzip', 'docx']}},
    windows = [{'script': "my_python_file.py"}],
    zipfile = None,
)

It seems that moving the python script to a different location produces the error.

  File "docx.pyc", line 1063, in savedocx
AssertionError

This is the savedocx line:

document = newdocument()
[...]
coreprops = coreproperties(title=title, subject=subject, creator=creator, keywords=keywords)
approps = appproperties()
contenttypes2 = contenttypes()
websettings2 = websettings()
wordrelationships2 = wordrelationships(relationships)
path_save = "C:\output"
savedocx(document, coreprops, approps, contenttypes2, websettings2, wordrelationships2, path_save)

The savedox is well writen as it works when it's not an .exe file.

How can I make the docx module work correctly? Do I've to add any other path/variable more when I make the exe?

Thanks in advance

Avión
  • 7,963
  • 11
  • 64
  • 105
  • 1
    What is the line that is raising the AssertionError? Also, is the code up on GitHub or somewhere I can inspect it? Not much to go on here I'm afraid. Also note that post-Word 2007 files are given a `.docx` extension rather than the old `.doc` extension. I also see that PIL or Pillow is not in the dependency list. – scanny Feb 10 '14 at 21:35
  • I added the line of the `savedoc` but as I said on the question it's not a programing problem of the `savedoc` line as it works perfectly when the `.exe` is not build. Thanks in advance. – Avión Feb 11 '14 at 10:03
  • I also added `PIL` to the `ìncludes` line but its not working either. – Avión Feb 11 '14 at 10:33
  • 1
    Sorry Borja, I don't have a clue then. Seems like a question for someone who knows about py2exe. The only thing I can think of that might be worth a try is to see if swapping in the new rewrite of python-docx and see if that works. The API is different so your .docx building code would need to be changed, but maybe if you just try a trivial three-line .docx file build and see if py2exe likes it: http://python-docx.readthedocs.org/ – scanny Feb 13 '14 at 03:09
  • I've also tried that one but it's not working either. I've the same problems, works perfectly without the .EXE and gives an error if the .EXE is build. This time shows up the following error: `PackageNotFoundError: Package not found at C:\Me\workspace\MugapeGUI\dist\guiMugapeMenu.exe\docx\templates\default.docx'` I copied the `docx\templates\` path to the current path, but it's taking the .exe as a path and it's impossible to solve. Any ideas scanny? Thanks in advance. – Avión Feb 13 '14 at 12:25
  • The entire error is: `File "Tkinter.pyc", line 1410, in __call__ File "guiMugapeMenu.py", line 1268, in File "guiMugapeMenu.py", line 1300, in guardar_planificacion_a_imprimir File "docx\api.pyc", line 31, in __init__ File "docx\api.pyc", line 152, in _open File "docx\opc\package.pyc", line 107, in open File "docx\opc\pkgreader.pyc", line 31, in from_file File "docx\opc\phys_pkg.pyc", line 31, in __new__ PackageNotFoundError: Package not found at 'C:\Me\workspace\MugapeGUI\dist\guiMugapeMenu.exe\docx\templates\default.docx'` – Avión Feb 13 '14 at 12:29
  • 1
    Ooh, that *is* a bit interesting. One thing the two packages have in common is that they have some "package data", files that are read in like data at runtime. They are "template" documents, the default starting places when you create a new Word document with e.g. `document = Document()`. This other SO answer might be a help: http://stackoverflow.com/questions/2747860/having-py2exe-include-my-data-files-like-include-package-data, also a search on 'py2exe package data' seems to turn up quite a bit. – scanny Feb 14 '14 at 07:24
  • I tried by including the entire `docx` folder, where the templates are located using `data_files`: `data_files = [('template', ['C:/Python27/Lib/site-packages/python_docx-0.3.0a5-py2.7.egg/docx/*'])],` but it shows me another error: `error: can't copy 'C:Python27\Lib\site-packages\python_docx-0.3.0a5-py2.7.egg\docx\*': doesn't exist or not a regular file` . And of course, it does exist! – Avión Feb 14 '14 at 11:51
  • The main problem is that in the path to seach the `docx\templates\default.docx` is adding the name of my `.exe` as you can see in the error: `C:\Me\workspace\MugapeGUI\dist\guiMugapeMenu.exe\docx\templates\default.docx` If I could remove that `guiMugapeMenu.exe` from the path the problem should be solved, as I can copy `\docx\templates\default.docx` manually. But I dont know where I've to do that 'remove the .exe from the path'. Any ideas? Thanks in advance. – Avión Feb 14 '14 at 11:56
  • 1
    I'm not familiar with py2exe behavior Borja, but from what I quickly read about it, it seems what you would want is something like this, if it can even work: `data_files = [('docx/template', ['C:/Python...2.7.egg/docx/templates/*'])]`. But it's really a py2exe question I'm afraid and I have no expertise with that package. – scanny Feb 15 '14 at 21:33
  • Thank for all your help. I tried that and it's not working either. This users has the same problem and tried the same solution, but nothing: http://stackoverflow.com/questions/10214105/py2exe-py2app-and-docx-dont-work-together – Avión Feb 17 '14 at 09:58
  • I finally found a solution. If you are interested, please check the answer @scanny . Have a good day and thanks for all the help! – Avión Feb 17 '14 at 10:35

2 Answers2

0

I solved the problem by edditing the api.py file of docx egg folder which is located in the Python folder of the system.

Changing this:

_thisdir = os.path.split(__file__)[0]
_default_docx_path = os.path.join(_thisdir, 'templates', 'default.docx')

To this:

thisdir = os.getcwd()
_default_docx_path = os.path.join(thisdir, 'templates', 'default.docx')

The first one was taking the actual running program and adding it to the path to locate the templates folder.
C:\myfiles\myprogram.exe\templates\default.docx

The solution takes only the path, not the running program.
C:\myfiles\templates\default.docx

Avión
  • 7,963
  • 11
  • 64
  • 105
0

Instead of changing some library file, I find it easier and cleaner to tell python-docx explicitly where to look for the template, i.e.:

document = Document('whatever/path/you/choose/to/some.docx')

This effectively solves the py2exe and docx path problem.

Apteryx
  • 5,822
  • 3
  • 16
  • 18