Làm cách nào để gzip nén một chuỗi trong Python?


86

Làm cách nào để gzip nén một chuỗi trong Python?

gzip.GzipFile tồn tại, nhưng đó là đối với các đối tượng tệp - còn với các chuỗi thuần túy thì sao?


1
@KevinDTimm, tài liệu đó chỉ đề cập đến StringIOnhưng không thực sự giải thích cách thực hiện. Vì vậy, đặt câu hỏi đó ở đây là hoàn toàn hợp lệ, IMHO. Tuy nhiên, một số thử nghiệm nữa trước khi hỏi và nói với chúng tôi về chúng sẽ rất tốt.
Alfe

@Alfe - câu hỏi đã bị đóng cách đây 4 năm vì lý do giống như nhận xét của tôi - OP đã không nỗ lực tìm kiếm trước.
KevinDTimm

4
Làm thế nào là chủ đề này?

2
Câu hỏi này là hit hàng đầu trong google hiện nay gzip string in pythonvà là IMO rất hợp lý. Nó nên được mở lại.
Garrett

2
Như ở trên, câu hỏi này là kết quả hàng đầu trong tìm kiếm trên google và một trong những câu trả lời là đúng - nó thực sự có vẻ như không nên đóng lại.
darkdan21

Câu trả lời:


156

Nếu bạn muốn tạo một gzipchuỗi nhị phân hoàn toàn tương thích, với tiêu đề, v.v., bạn có thể sử dụng gzip.GzipFilecùng với 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
Ngược lại với điều này là: `def gunzip_text (text): infile = StringIO.StringIO () infile.write (text) with gzip.GzipFile (fileobj = infile, mode =" r ") as f: f.rewind () f .read () return out.getvalue ()
fastmultiplication

3
@fastmultiplication: hoặc ngắn hơn:f = gzip.GzipFile(StringIO.StringIO(text)); result = f.read(); f.close(); return result
Alfe

2
Thật không may, câu hỏi đã được gần, vì vậy tôi không thể đưa ra một câu trả lời mới, nhưng đây là làm thế nào để làm điều này bằng Python 3.
Garrett

Có lẽ không liên quan, nén trong bộ nhớ trước tiên nhanh hơn (sử dụng đĩa cục bộ)?
user3226167

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

Cách dễ nhất là zlib mã hóa :

compressed_value = s.encode("zlib")

Sau đó, bạn giải nén nó bằng:

plain_string_again = compressed_value.decode("zlib")

1
@Daniel: Có, slà một đối tượng Python 2.x kiểu str.
Sven Marnach

2
Xem Mã hóa tiêu chuẩn để biết nơi anh ta nhận được điều đó (cuộn xuống "codec" ). Cũng có sẵn: s.encode('rot13'),s.encode( 'base64' )
bobobobo

8
Lưu ý rằng phương pháp này không tương thích với tiện ích dòng lệnh gzip trong đó gzip bao gồm tiêu đề và tổng kiểm tra, trong khi cơ chế này chỉ đơn giản nén nội dung.
tylerl 29/1213

Tôi biết điều này là cũ nhưng bạn dòng mã cho giải nén nên là: plain_string_again = compressed_value.decode("zlib")
minillinim

6
@BenjaminToueg: Python 3 nghiêm ngặt hơn về sự phân biệt giữa chuỗi Unicode (loại strtrong Python 3) và chuỗi byte (loại bytes). strcác đối tượng có một encode()phương thức trả về một bytesđối tượng và bytescác đối tượng có một decode()phương thức trả về a str. Các zlibcodec là đặc biệt ở chỗ nó chuyển đổi từ bytestới bytes, vì vậy nó không phù hợp với cấu trúc này. Bạn có thể sử dụng codecs.encode(b, "zlib")codecs.decode(b, "slib")cho một bytesđối tượng bthay thế.
Sven Marnach

22

Phiên bản Python3 của câu trả lời năm 2011 của Sven Marnach:

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

2
Trong Python 3 zlibvẫn được sử dụng, gziptrên thực tế sử dụng zlib, xem: docs.python.org/3/library/zlib.htmldocs.python.org/3/library/gzip.html#module-gzip
gitaarik

Câu trả lời ban đầu của tôi là sử dụng zlib. Đã thay đổi thành gzip vì đó là câu hỏi ban đầu. Bạn có thể dễ dàng thay thế từ gzip thành zlib (tìm kiếm và thay thế) trong ví dụ của tôi và nó sẽ hoạt động.
Punnerud

2

Đối với những người muốn nén khung dữ liệu Pandas ở định dạng JSON:

Đã thử nghiệm với Python 3.6 và 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
Tôi đoán câu hỏi là về việc nén một chuỗi trong bộ nhớ mà không cần phải ghi nó vào đĩa trong quá trình này. Nếu không thì câu trả lời của bạn là hoàn toàn chính xác.
Alfe
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.