Wie komprimiere ich einen String in Python?


85

Wie komprimiere ich einen String in Python?

gzip.GzipFile existiert, aber das ist für Dateiobjekte - was ist mit einfachen Zeichenfolgen?


1
@ KevinDTimm, dieses Dokument erwähnt nur, erklärt StringIOaber nicht wirklich, wie es geht. Diese Frage hier zu stellen ist also völlig gültig, IMHO. Noch ein paar Versuche, bevor wir gefragt und uns davon erzählt haben, wären allerdings nett gewesen.
Alfe

@ Alfe - Die Frage wurde vor 4 Jahren aus dem gleichen Grund wie mein Kommentar geschlossen. Das OP hat keine Anstrengungen unternommen, um zuerst zu suchen.
KevinDTimm

4
Wie ist das nicht zum Thema?

2
Diese Frage ist jetzt der Top-Hit in Google gzip string in pythonund ist IMO sehr vernünftig. Es sollte wieder geöffnet werden.
Garrett

2
Wie oben ist diese Frage das Top-Ergebnis einer Google-Suche, und eine der Antworten ist richtig - es scheint wirklich so, als ob sie nicht geschlossen werden sollte.
darkdan21

Antworten:


156

Wenn Sie eine komplette produzieren wollen gzip-kompatible Binärkette, mit dem Header etc, könnten Sie gzip.GzipFilezusammen mit 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'

2
Das Gegenteil davon ist: `def gunzip_text (text): infile = StringIO.StringIO () infile.write (text) mit gzip.GzipFile (fileobj = infile, mode =" r ") als f: f.rewind () f .read () return out.getvalue ()
Fastmultiplication

3
@fastmultiplication: oder kürzer:f = gzip.GzipFile(StringIO.StringIO(text)); result = f.read(); f.close(); return result
Alfe

2
Leider war die Frage nah, so dass ich keine neue Antwort geben kann, aber hier ist, wie dies in Python 3 gemacht wird.
Garrett

Ist die Komprimierung im Speicher wahrscheinlich schneller (unter Verwendung einer lokalen Festplatte)?
user3226167

1
In 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

65

Der einfachste Weg ist die zlib Kodierung :

compressed_value = s.encode("zlib")

Dann dekomprimieren Sie es mit:

plain_string_again = compressed_value.decode("zlib")

1
@ Daniel: Ja, sist ein Python 2.x-Objekt vom Typ str.
Sven Marnach

2
Siehe Standard-Codierungen, woher er das hat (scrollen Sie nach unten zu "Codecs" ). Ebenfalls erhältlich : s.encode('rot13'),s.encode( 'base64' )
Bobobobo

8
Beachten Sie, dass diese Methode nicht mit dem Befehlszeilenprogramm gzip kompatibel ist, da gzip einen Header und eine Prüfsumme enthält, während dieser Mechanismus den Inhalt einfach komprimiert.
Tyler

Ich weiß, dass dies alt ist, aber plain_string_again = compressed_value.decode("zlib")
Ihre

5
@BenjaminToueg: In Python 3 wird die Unterscheidung zwischen Unicode-Zeichenfolgen (Typ strin Python 3) und Byte-Zeichenfolgen (Typ bytes) strenger . strObjekte haben eine encode()Methode, die ein bytesObjekt zurückgibt , und bytesObjekte haben eine decode()Methode, die a zurückgibt str. Der zlibCodec ist insofern besonders, als er von bytesnach konvertiert bytes, sodass er nicht in diese Struktur passt. Sie können stattdessen codecs.encode(b, "zlib")und codecs.decode(b, "slib")für ein bytesObjekt bverwenden.
Sven Marnach

19

Python3-Version von Sven Marnach's Antwort von 2011:

import gzip
exampleString = 'abcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijmortenpunnerudengelstadrocksklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuv123'
compressed_value = gzip.compress(bytes(exampleString,'utf-8'))
plain_string_again  = gzip.decompress(compressed_value)

1
In Python 3 zlibwird immer noch verwendet, gziptatsächlich verwendet zlib, siehe: docs.python.org/3/library/zlib.html und docs.python.org/3/library/gzip.html#module-gzip
gitaarik

Meine ursprüngliche Antwort war die Verwendung von zlib. In gzip geändert, da dies die ursprüngliche Frage war. Sie können in meinem Beispiel leicht von gzip nach zlib (Suchen und Ersetzen) ersetzen, und es wird funktionieren.
Punnerud

2

Für diejenigen, die einen Pandas-Datenrahmen im JSON-Format komprimieren möchten:

Getestet mit Python 3.6 und 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())

-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()

4
Ich denke, die Frage war, einen String im Speicher zu komprimieren, ohne ihn dabei auf die Festplatte schreiben zu müssen. Ansonsten ist Ihre Antwort völlig richtig.
Alfe
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.