Search code examples
pythonpython-3.xpy2execx-freeze

Turn script to executable including data files in far-flung folder


I've got a small application I've built as a utility for the other members of my office. I'm an I.T. guy in a decidedly non-technological industry, so I'm trying to make this as simple as possible while still giving myself the ability to change the program without re-freezing it in its entirety. My program, therefore, looks like this:

| C:\Program Files (x86)\company_name\product_name
| | findppw.exe (my script)
| | runtime files that are built during the freeze
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
| %APPDATA%\company_name\product_name\
| | Reports\
| | | This gets filled with temp files only
| | Logs\
| | | This gets filled with log files
| | config.ini
| | stores.ini

I'm having some trouble with preparing the %APPDATA% folder, which should be the focus of this question.

My findppw.pyw script has the following imports:

from tkinter import *
from tkinter import ttk
import threading
from collections import OrderedDict
import datetime
import zipfile
from tempfile import NamedTemporaryFile
import queue
import os,sys # for sys.exit and os.startfile
import logging
from appdirs import AppDirs # to find %appdata% equivalent
import ast # for literal_eval of info in stores.ini and config.ini

I've tried using both cx_Freeze and py2exe for the freezing of it.

py2exe:

py2exe will compile the program correctly with or without a setup script, but in both cases the resulting executable throws a Windows error when launched: "Find Paperwork has stopped working" with no further information. The log files created by the dump are of no use to me in troubleshooting, though I can provide them upon request if someone think they'll be useful.

cx_Freeze:

When py2exe failed me, I went looking for an alternative and found cx_Freeze. It promised the ability to use an installer ("hooray," I think, "that should handle the %APPDATA% setup for me!") but I'm a little lost on how to set up the setup.py to handle it in this way, indeed if it's even possible! My alternative is to make an initialize function in my script that checks for the existence of these folders/files and creates them to some initial hard-coded value if they do not exist. That just FEELS like the work of an installer, though, not the executable.

As an upshot, though, the executable functions so there's that....

The Question:

How can I write a setup.py script for cx_Freeze EDIT: an excellent comment recommended use of pyinstaller as well, so let me amend this to say ANY library that throws data files in the right place, while leaving me with a windows installer I can use to distribute the program to other intraoffice systems?

Corollary, but likely outside of the scope of this question: why did the py2exe method fail?


Solution

  • I would disagree that this is a job for the installer. If you incorporate a check (How to check if a directory exists and create it if necessary?) every time you start the program, your program won't be bricked if the appdata folder disappears.

    If you need to write to the ini files after installation, they should be in the appdata folder. In that case, the copies in the program folder serve as templates, and can be copied as needed.

    Regarding cx_freeze: Use command python setup.py bdist_msi to make msi. There are samples for setup files in https://bitbucket.org/anthony_tuininga/cx_freeze/src/bd72fda4b395257c3d8e170213c039f2da40dd2f/cx_Freeze/samples/?at=default, and also in the cx_freeze installation. Documentation is at http://cx-freeze.readthedocs.org/en/latest/index.html.