Как сжать строку в Python с помощью gzip?

87

Как сжать строку в Python с помощью gzip?

gzip.GzipFile существует, но это для файловых объектов - как насчет простых строк?

Bdfy
источник
1
@KevinDTimm, в этом документе только упоминается, StringIOно не объясняется, как это сделать. Так что задать этот вопрос здесь совершенно справедливо, ИМХО. Тем не менее, было бы неплохо еще несколько испытаний, прежде чем спрашивать и рассказывать нам о них.
Alfe
@Alfe - вопрос был закрыт 4 года назад по той же причине, что и мой комментарий - OP не предпринял никаких усилий для поиска в первую очередь.
KevinDTimm
4
Как это не по теме?
2
Этот вопрос сейчас является самым популярным в Google, gzip string in pythonи это очень разумно, ИМО. Его следует снова открыть.
Garrett
2
Как и выше, этот вопрос является первым результатом поиска в Google, и один из ответов правильный - действительно кажется, что его не следует закрывать.
darkdan21

Ответы:

156

Если вы хотите создать полностью gzipсовместимую двоичную строку с заголовком и т. Д., Вы можете использовать gzip.GzipFileвместе с 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
источник
2
Противоположность этому: `def gunzip_text (текст): infile = StringIO.StringIO () infile.write (текст) с gzip.GzipFile (fileobj = infile, mode =" r ") как f: f.rewind () f .read () return out.getvalue ()
fastmultiplication
3
@fastmultiplication: или короче:f = gzip.GzipFile(StringIO.StringIO(text)); result = f.read(); f.close(); return result
Alfe
2
К сожалению, вопрос уже близок, поэтому я не могу дать новый ответ, но вот как это сделать в Python 3.
Гарретт,
Наверное, не связано, сначала сжатие в памяти происходит быстрее (с использованием локального диска)?
user3226167 05
1
В 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;
острокач
64

Самый простой способ - это zlib кодировка :

compressed_value = s.encode("zlib")

Затем вы распаковываете его с помощью:

plain_string_again = compressed_value.decode("zlib")
Свен Марнах
источник
1
@Daniel: Да, sэто Python 2.x объект типа str.
Sven Marnach
2
См. Стандартные кодировки, чтобы узнать, где он это взял (прокрутите вниз до «кодеков» ). Также в наличии: s.encode('rot13'),s.encode( 'base64' )
bobobobo
8
Обратите внимание, что этот метод несовместим с утилитой командной строки gzip, поскольку gzip включает заголовок и контрольную сумму, в то время как этот механизм просто сжимает содержимое.
Tylerl
Я знаю, что это plain_string_again = compressed_value.decode("zlib")
устарело,
6
@BenjaminToueg: Python 3 строже различает строки Unicode (тип strв Python 3) и байтовые строки (тип bytes). strу объектов есть encode()метод, который возвращает bytesобъект, а у bytesобъектов есть decode()метод, возвращающий str. zlibКодек особенного в том , что он преобразует bytesв bytes, так что это не вписывается в эту структуру. Вместо этого вы можете использовать codecs.encode(b, "zlib")и codecs.decode(b, "slib")для bytesобъекта b.
Sven Marnach
22

Версия Python3 ответа Свена Марнака 2011 года:

import gzip
exampleString = 'abcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijmortenpunnerudengelstadrocksklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuvabcdefghijklmnopqrstuv123'
compressed_value = gzip.compress(bytes(exampleString,'utf-8'))
plain_string_again  = gzip.decompress(compressed_value)
Пуннеруд
источник
2
В Python 3 zlibвсе еще используется, gzipфактически использует zlib, см .: docs.python.org/3/library/zlib.html и docs.python.org/3/library/gzip.html#module-gzip
gitaarik
В моем первоначальном ответе использовался zlib. Изменен на gzip, потому что это был исходный вопрос. В моем примере вы можете легко заменить gzip на zlib (поиск и замена), и это сработает.
Punnerud
2

Для тех, кто хочет сжать фрейм данных Pandas в формате JSON:

Протестировано с Python 3.6 и 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
Я предполагаю, что вопрос был о сжатии строки в памяти без необходимости записывать ее на диск в процессе. В противном случае ваш ответ абсолютно правильный.
Alfe