Python: Open file in zip without temporarily extracting it
PythonZipPython Problem Overview
How can I open files in a zip archive without extracting them first?
I'm using pygame. To save disk space, I have all the images zipped up.
Is it possible to load a given image directly from the zip file?
For example:
pygame.image.load('zipFile/img_01')
Python Solutions
Solution 1 - Python
Vincent Povirk's answer won't work completely;
import zipfile
archive = zipfile.ZipFile('images.zip', 'r')
imgfile = archive.open('img_01.png')
...
You have to change it in:
import zipfile
archive = zipfile.ZipFile('images.zip', 'r')
imgdata = archive.read('img_01.png')
...
For details read the ZipFile
docs here.
Solution 2 - Python
import io, pygame, zipfile
archive = zipfile.ZipFile('images.zip', 'r')
# read bytes from archive
img_data = archive.read('img_01.png')
# create a pygame-compatible file-like object from the bytes
bytes_io = io.BytesIO(img_data)
img = pygame.image.load(bytes_io)
I was trying to figure this out for myself just now and thought this might be useful for anyone who comes across this question in the future.
Solution 3 - Python
In theory, yes, it's just a matter of plugging things in. Zipfile can give you a file-like object for a file in a zip archive, and image.load will accept a file-like object. So something like this should work:
import zipfile
archive = zipfile.ZipFile('images.zip', 'r')
imgfile = archive.open('img_01.png')
try:
image = pygame.image.load(imgfile, 'img_01.png')
finally:
imgfile.close()
Solution 4 - Python
From Python 3.2 onwards it has been possible to use the ZipFile
as a context manager:
from zipfile import ZipFile
with ZipFile('images.zip') as zf:
for file in zf.namelist():
if not file.endswith('.png'): # optional filtering by filetype
continue
with zf.open(file) as f:
image = pygame.image.load(f, namehint=file)
- The plus side of using context managers (
with
statement) is that the files are automatically closed properly. - The
f
can be used like regular file object you would get when using the built-in open().