TGViewer
Python Заметки Python Заметки @pythonotes · 2.2K subscribers
Post #155 1.21K
Вы знаете, что строки в Python можно кодировать и декодировать в разные кодировки.

>>> s = 'Привет'
>>> s.encode() # в байты
b'\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82'

>>> s.encode('ascii') # в ASCII (если получится)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)

>>> s.encode('euc_jp') # японская кодировка
b'\xa7\xb1\xa7\xe2\xa7\xda\xa7\xd3\xa7\xd6\xa7\xe4'

>>> s.encode('hz') # Simplified Chinese
b"~{'1'b'Z'S'V'd~}"

И другие...

А можно ли добавить свою кодировку в этот список?
Можно! И сейчас мы это сделаем. Давайте добавим ZIP-кодировку из Python2, о которой мы говорили в прошлом посте.

Для начала нам нужен алгоритм. Я хочу сжимать строку через ZIP и после получения байтов преобразовывать их в строку через base64 (можно и без base64). Получится такой код:

import zlib, base64

>>> orig = 'hello python'
>>> compressed = zlib.compress(orig.encode(), 5)
>>> compresed_b = base64.encodebytes(compressed)
>>> print(compresed_b)
b'eF7LSM3JyVcoqCzJyM8DAB7wBNc='

Да, строка получилась длинней чем была. Но мы помним, что всё будет иначе если исходная строка большая.

Обратный алгоритм декодирования

>>> compressed = base64.decodebytes(compresed_b)
>>> restored = zlib.decompress(compressed).decode()
>>> orig == restored
True

Отлично! 😎
Теперь, чтобы создать кодек на базе этих алгоритмов, следует воспользоваться функций codecs.register().
В неё подаётся имя функции которая должна вернуть объект codecs.CodecInfo.
Данный объект будет содержать две функции - кодирование и декодирование. Это и будет наш кодек.
Давайте назовём наш кодек просто "z". Тогда его создание будет выглядеть как-то так:

import zlib, base64, codecs

def z_encode(data):
return base64.encodebytes(zlib.compress(data.encode(), 5)), 0

def z_decode(data):
return zlib.decompress(base64.decodebytes(data)).decode(), 0

def z_search(encoding_name):
return codecs.CodecInfo(z_encode, z_decode, name='z')

codecs.register(z_search)

Тестим!

>>> s = 'Hello New codec!'
>>> s_enc = s.encode('z')
>>> print(s_enc)
b'eF7zSM3JyVfwSy1XSM5PSU1WBAAvxwV+\n'

Теперь обратно

>>> s_enc.decode('z')
'Hello New codec!'

А теперь практика!. Сжимаем JSON со списком файлов

>>> from pathlib import Path
>>> import json

>>> files = list(map(str, list(Path('~/Documents').expanduser().glob('**/*'))))
>>> print(len(files))
5390
>>> text = json.dumps(files)
>>> print(len(text))
513839
>>> enc = text.encode('z')
>>> print(len(enc))
53317

Профит почти в 10 раз!
Можно еще уменьшить размер если обойтись без BASE64. Но тогда вы получите чистые байты и как строку их передать уже не получится.

PS. А вот стандартный и самый короткой способ для ZIP-сжатия байтов в Python3

>>> import codecs
>>> codecs.encode(my_bytes, 'zip'))

(спасибо @amarovita за пример кода)
#tricks
More from @pythonotes
  1. Sep 21, 2026­ WebAssembly это мощная технология позволяющая загружать практически любое приложение в б…
  2. Aug 17, 2026Не так давно столкнулся с API который в ответе с ошибкой присылал только статус-код. Без п…
  3. Jul 20, 2026У меня основная ОС это Linux. Но нередко требуется делать сборку клиента под Windows. Соби…
  4. Jul 13, 2026В прошлый раз был пример с понижением привелегий процесса. Проблема в том, что обратно под…
  5. Jul 6, 2026Модуль pwd может использоваться для считывания информации о пользователях из базы данных п…
  6. Jun 22, 2026Недавно я реализовал Multi Tenancy систему на FastAPI + SQLAlchemy и пересобрал её в небол…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →