Bagaimana cara mengompresi gzip string dengan Python?

87

Bagaimana cara mengompresi gzip string dengan Python?

gzip.GzipFile ada, tapi itu untuk objek file - bagaimana dengan string biasa?

Bdfy.dll
sumber
1
@KevinDTT, dokumen tersebut hanya menyebutkan StringIOtetapi tidak benar-benar menjelaskan cara melakukannya. Jadi menanyakan pertanyaan itu di sini sepenuhnya valid, IMHO. Namun, beberapa pencobaan lagi sebelum bertanya dan memberi tahu kami tentang itu akan menyenangkan.
Alfe
@Alfe - pertanyaannya ditutup 4 tahun yang lalu karena alasan yang sama dengan komentar saya - OP tidak berusaha mencari terlebih dahulu.
KevinDTimm
4
Bagaimana ini di luar topik?
2
Pertanyaan ini adalah hit teratas di google sekarang gzip string in pythondan IMO sangat masuk akal. Ini harus dibuka kembali.
Garrett
2
Seperti di atas, pertanyaan ini adalah hasil teratas dalam pencarian google, dan salah satu jawabannya benar - sepertinya pertanyaan ini tidak boleh ditutup.
darkdan21

Jawaban:

156

Jika Anda ingin menghasilkan gzipstring biner yang kompatibel dengan lengkap , dengan header dll, Anda dapat menggunakan gzip.GzipFilebersama dengan 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
sumber
2
Kebalikan dari ini adalah: `def gunzip_text (text): infile = StringIO.StringIO () infile.write (text) dengan gzip.GzipFile (fileobj = infile, mode =" r ") as f: f.rewind () f .read () return out.getvalue ()
fastmultiplication
3
@fastmultiplication: atau lebih pendek:f = gzip.GzipFile(StringIO.StringIO(text)); result = f.read(); f.close(); return result
Alfe
2
Sayangnya, pertanyaannya sudah dekat, jadi saya tidak bisa membuat jawaban baru, tetapi inilah cara melakukannya dengan Python 3.
Garrett
Mungkin tidak terkait, apakah mengompresi memori terlebih dahulu lebih cepat (menggunakan disk lokal)?
pengguna3226167
1
Dengan 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

Cara termudah adalah dengan zlib encoding :

compressed_value = s.encode("zlib")

Kemudian Anda mendekompresi dengan:

plain_string_again = compressed_value.decode("zlib")
Sven Marnach
sumber
1
@ Daniel: Ya, sadalah objek 2.x Python jenis str.
Sven Marnach
2
Lihat Pengkodean Standar untuk mengetahui dari mana dia mendapatkannya (gulir ke bawah ke "codec" ). Juga tersedia: s.encode('rot13'),s.encode( 'base64' )
bobobobo
8
Perhatikan bahwa metode ini tidak kompatibel dengan utilitas baris perintah gzip karena gzip menyertakan header dan checksum, sementara mekanisme ini hanya memampatkan konten.
tylerl
Saya tahu ini sudah tua tetapi Anda baris kode untuk dekompresi harus: plain_string_again = compressed_value.decode("zlib")
minillinim
6
@BenjaminToueg: Python 3 lebih ketat tentang perbedaan antara string Unicode (ketik strPython 3) dan string byte (tipe bytes). strobjek memiliki encode()metode yang mengembalikan bytesobjek, dan bytesobjek memiliki decode()metode yang mengembalikan str. The zlibcodec khusus dalam hal itu mengkonversi dari byteske bytes, sehingga tidak cocok dengan struktur ini. Anda dapat menggunakan codecs.encode(b, "zlib")dan codecs.decode(b, "slib")untuk bytesobjek bsebagai gantinya.
Sven Marnach
22

Versi Python3 dari jawaban 2011 Sven Marnach:

import gzip
exampleString = 'abcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijmortenpunnerudengelstadrocksklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuv123'
compressed_value = gzip.compress(bytes(exampleString,'utf-8'))
plain_string_again  = gzip.decompress(compressed_value)
Punnerud
sumber
2
Di Python 3 zlibmasih digunakan, gzipsebenarnya menggunakan zlib, lihat: docs.python.org/3/library/zlib.html dan docs.python.org/3/library/gzip.html#module-gzip
gitaarik
Jawaban asli saya menggunakan zlib. Diubah menjadi gzip karena itu pertanyaan asli. Anda dapat dengan mudah mengganti dari gzip ke zlib (cari-dan-ganti) dalam contoh saya, dan ini akan berhasil.
Punnerud
2

Bagi mereka yang ingin mengompres dataframe Pandas dalam format JSON:

Diuji dengan Python 3.6 dan 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
sumber
-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
sumber
4
Saya kira pertanyaannya adalah tentang mengompresi string dalam memori tanpa harus menuliskannya ke disk dalam prosesnya. Jika tidak, jawaban Anda sepenuhnya benar.
Alfe