Python: abre el archivo en zip sin extraerlo temporalmente

82

¿Cómo puedo abrir archivos en un archivo zip sin extraerlos primero?

Estoy usando pygame. Para ahorrar espacio en disco, tengo todas las imágenes comprimidas. ¿Es posible cargar una imagen determinada directamente desde el archivo zip? Por ejemplo: pygame.image.load('zipFile/img_01')

usuario2880847
fuente
2
¿Qué tipo de archivos de imagen? GIF, JPEG y PNG ya están comprimidos.
hughdbrown

Respuestas:

109

La respuesta de Vincent Povirk no funcionará por completo;

import zipfile
archive = zipfile.ZipFile('images.zip', 'r')
imgfile = archive.open('img_01.png')
...

Tienes que cambiarlo en:

import zipfile
archive = zipfile.ZipFile('images.zip', 'r')
imgdata = archive.read('img_01.png')
...

Para obtener más información, lea los ZipFiledocumentos aquí .

Jellema
fuente
image = pygame.image.load (imgfile, 'img_01.png') TypeError: debe ser una cadena sin bytes nulos, no str
user2880847
Explique su cambio. read devuelve una cadena con el contenido del archivo; open devuelve un objeto similar a un archivo. La documentación de pygame dice que image.load quiere un nombre de archivo o un objeto similar a un archivo.
Esme Povirk
@Vincent Povirk: Gracias por comentar. El problema sigue siendo que image.load acepta un objeto similar a un archivo, pero no acepta el objeto zip-file. Tienes que adaptarte a eso de alguna manera. Tampoco estoy convencido de mi respuesta, aún no es elegante ...
Jellema
21
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)

Estaba tratando de resolver esto por mí mismo hace un momento y pensé que esto podría ser útil para cualquiera que se encuentre con esta pregunta en el futuro.

Brandon
fuente
8

En teoría, sí, es solo una cuestión de conectar cosas. Zipfile puede darle un objeto similar a un archivo para un archivo en un archivo zip, e image.load aceptará un objeto similar a un archivo. Entonces, algo como esto debería funcionar:

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()
Esme Povirk
fuente