python: can executable zip files include data files?

Being fairly new to python I only recently discovered the ability to directly execute a .zip file by placing a __main__.py file at the top of the file. This works great for python code, but can I bundle other types of files and access them with my scripts? If so, how?

My ultimate goal would be to bundle some image files along with the python code in a single .zip file, then be able to use those images within the app without having to extract them to disk. I also would like to bundle a copyright notice, release notes, etc so that the entire app and its data files is in a single zip that can be executed without having to extract it somewhere.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You could use pkg_resources functions to access files:

# __main__.py
import pkg_resources
from PIL import Image

print pkg_resources.resource_string(__name__, 'README.txt')

im = Image.open(pkg_resources.resource_stream('app', 'im.png'))
im.rotate(45).show()

Where zipfile contains:

.
|-- app
|   |-- im.png
|   `-- __init__.py
|-- README.txt
`-- __main__.py

To make zipfile executable, run:

$ echo '#!/usr/bin/env python' | cat - zipfile > program-name
$ chmod +x program-name

To test it:

$ cp program-name /another-dir/
$ cd /another-dir && ./program-name

Method 2

At least on my Linux box there is no open filehandle or mapped memory by the process to its own zipfile, so presumably there is no way to “magically” access it.

However, creating your own access is not that hard. Create a __main__.py like so:

import os, zipfile

me = zipfile.ZipFile(os.path.dirname(__file__), 'r')
f = me.open('other.txt')
print f.read()
f.close()
me.close()

Edit: Somewhat terse, that. For completeness:

$ echo "Hello ZIP" > other.txt
$ zip testo.zip __main__.py other.txt
$ python testo.zip
Hello ZIP

Method 3

You can simply use pkgutil.get_data() as suggested in this answer.

Method 4

pkgutil.get_data(package, resource) takes the name of a package and a resource. That means you have to put your data files inside a package within the zip file.

So for example a zip file containing:

__main__.py
zippeddata/__init__.py
zippeddata/data.txt

The __init__.py file can be empty or just a comment, but you need one to make zippeddata importable.

Then in __main__.py you just call:

data = pkgutil.get_data('zippeddata', 'data.txt')


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x