Python'da bir dizeyi nasıl gzip sıkıştırabilirim?


87

Python'da bir dizeyi nasıl gzip sıkıştırabilirim?

gzip.GzipFile var, ancak bu dosya nesneleri için - peki ya düz dizeler?


1
@KevinDTimm, bu belge sadece bahsediyor StringIOama nasıl yapılacağını gerçekten açıklamıyor. Yani bu soruyu burada sormak tamamen geçerli, IMHO. Yine de, onları sormadan ve bize söylemeden önce birkaç deneme daha iyi olurdu.
Alfe

@Alfe - soru 4 yıl önce benim yorumumla aynı nedenle kapatıldı - OP ilk önce arama yapmak için hiçbir çaba sarf etmedi.
KevinDTimm

4
Bu nasıl konu dışı?

2
Bu soru şu anda google'da en çok hit gzip string in pythonve çok makul IMO. Yeniden açılmalıdır.
Garrett

2
Yukarıdaki gibi, bu soru bir google aramasında en iyi sonuçtur ve cevaplardan biri doğrudur - gerçekten kapatılmaması gerektiği gibi görünüyor.
darkdan21

Yanıtlar:


156

Eğer tam üretmek istiyorsanız gzipbaşlığı vs ile uyumlu bir ikili dize şunu kullanabilirsiniz gzip.GzipFilebirlikte 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
Bunun tersi şudur: "def gunzip_text (text): infile = StringIO.StringIO () infile.write (text) ile gzip.GzipFile (fileobj = infile, mode =" r ") f: f.rewind () f olarak .read () return out.getvalue ()
fastmultiplication

3
@fastmultiplication: veya daha kısa:f = gzip.GzipFile(StringIO.StringIO(text)); result = f.read(); f.close(); return result
Alfe

2
Maalesef soru yaklaştı, bu yüzden yeni bir cevap veremem, ancak işte bunu Python 3'te nasıl yapacağım.
Garrett

Muhtemelen ilgisiz, bellekte sıkıştırma önce daha hızlı mı (yerel disk kullanılarak)?
user3226167

1
Python 3'te: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

En kolay yol zlib kodlamadır :

compressed_value = s.encode("zlib")

Daha sonra şunu açarsınız:

plain_string_again = compressed_value.decode("zlib")

1
@Daniel: Evet, sPython 2.x türünde bir nesnedir str.
Sven Marnach

2
Bunu nereden aldığını görmek için Standart Kodlamalara bakın ( "kodekler" e gidin ). Ayrıca mevcut: s.encode('rot13'),s.encode( 'base64' )
bobobobo

8
Bu yöntemin, gzip'in bir başlık ve sağlama toplamı içerdiğinden, gzip komut satırı yardımcı programıyla uyumsuz olduğunu, bu mekanizmanın ise içeriği sıkıştırdığını unutmayın.
tylerl

Bunun eski olduğunu biliyorum ama açma için kod satırınız şöyle olmalıdır: plain_string_again = compressed_value.decode("zlib")
minillinim

6
@BenjaminToueg: Python 3, Unicode dizeleri ( strPython 3'te tür) ve bayt dizeleri (tür bytes) arasındaki ayrım konusunda daha katıdır . strnesnelerin encode()bir bytesnesneyi döndüren bir yöntemi vardır ve bytesnesnelerin decode()bir str. zlibOndan dönüştürür ki codec'i özeldir bytesiçin bytesbu yapıya uymuyor yani. Bunun yerine bir nesne için codecs.encode(b, "zlib")ve kullanabilirsiniz . codecs.decode(b, "slib")bytesb
Sven Marnach

22

Sven Marnach'ın 2011 cevabının Python3 versiyonu:

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

2
Python 3'te zlibhala kullanılıyor, gzipaslında kullanıyor zlib, bkz: docs.python.org/3/library/zlib.html ve docs.python.org/3/library/gzip.html#module-gzip
gitaarik

Orijinal cevabım zlib kullanıyordu. Orijinal soru olduğu için gzip olarak değiştirildi. Örneğimde gzip'ten zlib'e (ara ve değiştir) kolayca değiştirebilirsiniz ve çalışacaktır.
Punnerud

2

Pandas veri çerçevesini JSON formatında sıkıştırmak isteyenler için:

Python 3.6 ve Pandas 0.23 ile test edildi

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
Sanırım soru, işlem sırasında diske yazmak zorunda kalmadan bellekteki bir dizeyi sıkıştırmakla ilgiliydi. Aksi takdirde cevabınız tamamen doğrudur.
Alfe
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.