¿Cómo comprimo gzip una cadena en Python?

86

¿Cómo comprimo gzip una cadena en Python?

gzip.GzipFile existe, pero eso es para objetos de archivo, ¿qué pasa con cadenas simples?

Bdfy
fuente
1
@KevinDTimm, ese documento solo menciona StringIOpero no explica realmente cómo hacerlo. Entonces, hacer esa pregunta aquí es completamente válido, en mi humilde opinión. Sin embargo, habría sido bueno hacer algunas pruebas más antes de preguntarnos y contarnos sobre ellas.
Alfe
@Alfe: la pregunta se cerró hace 4 años por la misma razón que mi comentario: el OP no hizo ningún esfuerzo por buscar primero.
KevinDTimm
4
¿Cómo es esto fuera de tema?
2
Esta pregunta es el mayor éxito en Google ahora gzip string in pythony es muy razonable en mi opinión. Debería volver a abrirse.
Garrett
2
Como se indicó anteriormente, esta pregunta es el resultado principal de una búsqueda en Google, y una de las respuestas es correcta; realmente parece que no debería cerrarse.
darkdan21

Respuestas:

156

Si desea producir una gzipcadena binaria completa compatible, con el encabezado, etc., puede usar gzip.GzipFilejunto con StringIO:

try:
    from StringIO import StringIO  # Python 2.7
except ImportError:
    from io import StringIO  # Python 3.x
import gzip
out = StringIO()
with gzip.GzipFile(fileobj=out, mode="w") as f:
  f.write("This is mike number one, isn't this a lot of fun?")
out.getvalue()

# returns '\x1f\x8b\x08\x00\xbd\xbe\xe8N\x02\xff\x0b\xc9\xc8,V\x00\xa2\xdc\xcc\xecT\x85\xbc\xd2\xdc\xa4\xd4"\x85\xfc\xbcT\x1d\xa0X\x9ez\x89B\tH:Q!\'\xbfD!?M!\xad4\xcf\x1e\x00w\xd4\xea\xf41\x00\x00\x00'
NPE
fuente
2
Lo contrario de esto es: `def gunzip_text (texto): infile = StringIO.StringIO () infile.write (text) con gzip.GzipFile (fileobj = infile, mode =" r ") como f: f.rewind () f .read () return out.getvalue ()
fastmultiplication
3
@fastmultiplication: o más corto:f = gzip.GzipFile(StringIO.StringIO(text)); result = f.read(); f.close(); return result
Alfe
2
Desafortunadamente, la pregunta ha estado cerca, así que no puedo dar una nueva respuesta, pero aquí se explica cómo hacerlo en Python 3.
Garrett
Probablemente no esté relacionado, ¿la compresión en la memoria primero es más rápida (usando el disco local)?
user3226167
1
En Python 3:import zlib; my_string = "hello world"; my_bytes = zlib.compress(my_string.encode('utf-8')); my_hex = my_bytes.hex(); my_bytes2 = bytes.fromhex(my_hex); my_string2 = zlib.decompress(my_bytes); assert my_string == my_string2;
ostrokach
64

La forma más sencilla es la zlib codificación :

compressed_value = s.encode("zlib")

Luego lo descomprimes con:

plain_string_again = compressed_value.decode("zlib")
Sven Marnach
fuente
1
@ Daniel: Sí, ses un objeto de Python 2.x de tipo str.
Sven Marnach
2
Consulte Codificaciones estándar para saber dónde lo obtuvo (desplácese hacia abajo hasta "códecs" ). También disponible: s.encode('rot13'),s.encode( 'base64' )
bobobobo
8
Tenga en cuenta que este método es incompatible con la utilidad de línea de comandos gzip en que gzip incluye un encabezado y una suma de comprobación, mientras que este mecanismo simplemente comprime el contenido.
tylerl
Sé que esto es viejo pero línea de código para descomprimir debe ser: plain_string_again = compressed_value.decode("zlib")
minillinim
6
@BenjaminToueg: Python 3 es más estricto sobre la distinción entre cadenas Unicode (tipo stren Python 3) y cadenas de bytes (tipo bytes). strlos objetos tienen un encode()método que devuelve un bytesobjeto y los bytesobjetos tienen un decode()método que devuelve un str. El zlibcódec es especial porque convierte de bytesa bytes, por lo que no encaja en esta estructura. Puede usar codecs.encode(b, "zlib")y codecs.decode(b, "slib")para un bytesobjeto en su blugar.
Sven Marnach
22

Versión Python3 de la respuesta de 2011 de Sven Marnach:

import gzip
exampleString = 'abcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijmortenpunnerudengelstadrocksklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuv123'
compressed_value = gzip.compress(bytes(exampleString,'utf-8'))
plain_string_again  = gzip.decompress(compressed_value)
Punnerud
fuente
2
En Python 3 zlibtodavía se usa, en gziprealidad se usa zlib, consulte: docs.python.org/3/library/zlib.html y docs.python.org/3/library/gzip.html#module-gzip
gitaarik
Mi respuesta original estaba usando zlib. Se cambió a gzip porque esa era la pregunta original. Puede reemplazar fácilmente de gzip a zlib (buscar y reemplazar) en mi ejemplo, y funcionará.
Punnerud
2

Para aquellos que quieran comprimir un marco de datos Pandas en formato JSON:

Probado con Python 3.6 y Pandas 0.23

import sys
import zlib, lzma, bz2
import math

def convert_size(size_bytes):
    if size_bytes == 0:
        return "0B"
    size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
    i = int(math.floor(math.log(size_bytes, 1024)))
    p = math.pow(1024, i)
    s = round(size_bytes / p, 2)
    return "%s %s" % (s, size_name[i])

dataframe = pd.read_csv('...') # your CSV file
dataframe_json = dataframe.to_json(orient='split')
data = dataframe_json.encode()
compressed_data = bz2.compress(data)
decompressed_data = bz2.decompress(compressed_data).decode()
dataframe_aux = pd.read_json(decompressed_data, orient='split')

#Original data size:  10982455 10.47 MB
#Encoded data size:  10982439 10.47 MB
#Compressed data size:  1276457 1.22 MB (lzma, slow), 2087131 1.99 MB (zlib, fast), 1410908 1.35 MB (bz2, fast)
#Decompressed data size:  10982455 10.47 MB
print('Original data size: ', sys.getsizeof(dataframe_json), convert_size(sys.getsizeof(dataframe_json)))
print('Encoded data size: ', sys.getsizeof(data), convert_size(sys.getsizeof(data)))
print('Compressed data size: ', sys.getsizeof(compressed_data), convert_size(sys.getsizeof(compressed_data)))
print('Decompressed data size: ', sys.getsizeof(decompressed_data), convert_size(sys.getsizeof(decompressed_data)))

print(dataframe.head())
print(dataframe_aux.head())
Andrews Sobral
fuente
-4
s = "a long string of characters"

g = gzip.open('gzipfilename.gz', 'w', 5) # ('filename', 'read/write mode', compression level)
g.write(s)
g.close()
Jon Mitten
fuente
4
Supongo que la pregunta era sobre la compresión de una cadena en la memoria sin tener que escribirla en el disco en el proceso. De lo contrario, su respuesta es totalmente correcta.
Alfe