Пользовательский кодек Charmap Python

1

Я пытаюсь написать собственный Python-кодек. Вот краткий пример:

import codecs

class TestCodec(codecs.Codec):
    def encode(self, input_, errors='strict'):
        return codecs.charmap_encode(input_, errors, {
            'a': 0x01,
            'b': 0x02,
            'c': 0x03,
        })

    def decode(self, input_, errors='strict'):
        return codecs.charmap_decode(input_, errors, {
            0x01: 'a',
            0x02: 'b',
            0x03: 'c',
        })

def lookup(name):
    if name != 'test':
        return None
    return codecs.CodecInfo(
        name='test',
        encode=TestCodec().encode,
        decode=TestCodec().decode,
    )

codecs.register(lookup)
print(b'\x01\x02\x03'.decode('test'))
print('abc'.encode('test'))

Декодирование работает, но кодировка выдает исключение:

$ python3 codectest.py
abc
Traceback (most recent call last):
  File "codectest.py", line 29, in <module>
    print('abc'.encode('test'))
  File "codectest.py", line 8, in encode
    'c': 0x03,
UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-2:
character maps to <undefined>

Любые идеи как правильно использовать charmap_encode?

Теги:
character-encoding
encoding

1 ответ

2
Лучший ответ

Посмотрите на https://docs.python.org/3/library/codecs.html#encodings-and-unicode (третий абзац):

Существует еще одна группа кодировок (так называемые кодировки charmap), которые выбирают другое подмножество всех кодовых точек Unicode и как эти кодовые точки отображаются в байты 0x0 - 0xff. Чтобы увидеть, как это сделать, просто откройте, например, encodings/cp1252.py (это кодировка, которая используется в основном в Windows). Theres строковая константа с 256 символами, которая показывает вам, какой символ сопоставлен какому байтовому значению.

возьмите подсказку, чтобы посмотреть на encodings/cp1252.py, и проверьте следующий код:

import codecs

class TestCodec(codecs.Codec):
    def encode(self, input_, errors='strict'):
        return codecs.charmap_encode(input_, errors, encoding_table)

    def decode(self, input_, errors='strict'):
        return codecs.charmap_decode(input_, errors, decoding_table)

def lookup(name):
    if name != 'test':
        return None
    return codecs.CodecInfo(
        name='test',
        encode=TestCodec().encode,
        decode=TestCodec().decode,
    )

decoding_table = (
    'z'
    'a'
    'b'
    'c'
)    
encoding_table=codecs.charmap_build(decoding_table)
codecs.register(lookup)

### --- following is test/debug code
print(ascii(encoding_table))

print(b'\x01\x02\x03'.decode('test'))
foo = 'abc'.encode('test')
print(ascii(foo))

Выход:

{97: 1, 122: 0, 99: 3, 98: 2}
abc
b'\x01\x02\x03'

Ещё вопросы

Сообщество Overcoder
Наверх
Меню