Search code examples
pythonpython-2.7setup.pydata-files

How to properly load data files in Python


So.. I have this little problem with my program. I might need to have some basic stuff explained - especially what happens when stuff is installed via distutils.

I have two icons that I'm using in my GUI application made in Tkinter. I have a problem with loading them because of their location.

You can see my setup.py file here. You can see my specified files on line 28 (they reside in subfolder gui/).

Of course the problem starts when you want to run GUI portion of the program (that can be done by installing it and run it as flashstudy --gui executable). I get error in file main.py on line 44 & 45 (the file is here). The images cannot be loaded from the location.

I guess it makes sense because it's supposed to look to the directory where the files were transferred during installation but I don't know where that place is and how to load it easily.

Another thing - the reason why it is set up that way is so you can run the program and GUI portion directly from terminal without installing it, I'd like to keep that functionality.

Is there a way to do this somehow?


Solution

  • If you use setuptools rather than distutils, you can reliably include data files and load them again after installation, regardless of how the data files were installed.

    You already import setuptools but are ignoring it otherwise; rather than import setup from distutils.core, import it from setuptools:

    from setuptools import setup
    

    Use the package_data or include_package_data, rather than the data_files option to include your images. See Including Data Files in the setuptools documentation:

    package_data = {'gui': ['*.gif']}
    

    You can then load your package data with the pkg_resources Resource API. For TKinter PhotoImage objects you need a filename, so you could use:

    icon_up = PhotoImage(
        file=pkg_resources.resource_filename('flashCardStudy', 'gui/up.gif'))
    

    Personally, I'd embed a base64 data string in the source instead, and use that as the icon:

    icon_up_data = '''\
        R0lGODlhEAAQAJEAAAAAAP///////wAAACH5BAEAAAIALAAAAAAQABAAAAIflI+pywfQ0ovuQWpv
        y3PzyHVKKErkQlpjqhmsSsVRAQA7
    '''
    icon_up = PhotoImage(data=icon_up_data)
    

    This bypasses the whole issue altogether. Note that this only works for GIF images however.