Преобразование между ISO-8859-2 и UTF-8 в Python

Мне интересно, как я могу преобразовать символы ISO-8859-2 (латинский-2) (я имею в виду целочисленные или шестнадцатеричные значения, которые представляют символы в кодировке ISO-8859-2) в символы UTF-8.

Что мне нужно сделать с моим проектом в Python:

  1. Получите шестнадцатеричные значения от последовательного порта, которые являются символами, закодированными в ISO-8859-2.
  2. Расшифруйте их, это - получить из них "стандартные" строки юникода python.
  3. Подготовьте и напишите XML-файл.

Использование Python 3.4.3

txt_str = "ąęłóźć"
txt_str.decode('ISO-8859-2')
Traceback (most recent call last): File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'decode'

Основная проблема по-прежнему заключается в подготовке правильного ввода для метода "decode" (он работает в python 2.7.10, и именно этот я использую в этом проекте). Как подготовить правильную строку из десятичного значения, которые являются латинскими-2 кодовыми числами?

Обратите внимание, что было бы очень сложно получать символы utf-8 из последовательного порта, благодаря используемым устройствам и ограничениям протокола связи.

Пример данных по запросу:

68632057
62206A75
7A647261
B364206F
20616775
777A616E
616A2061
6A65696B
617A20B6
697A7970
6A65B361
70697020
77F36469
62202C79
6E647572
75206A65
7963696C
72656D75
6A616E20
73726F67
206A657A
65647572
77207972
73772065
00000069

Это пример данных. ISO-8859-2 выдвинут в uint32, 4 символа за int.

немного кода, который управляет распаковкой:

l = l[7:].replace(",", "").replace(".", "").replace("\n","").replace("\r","") # crop string from uart, only data left
vl = [l[0:2], l[2:4], l[4:6], l[6:8]] # list of bytes
vl = vl[::-1] # reverse them - now in actual order

Чтобы получить целочисленное значение из шестнадцатеричной строки, я могу просто использовать:

int_vals = [int(hs, 16) for hs in vl]

3 ответа

Интересные примеры данных. В идеале ваши образцы данных должны быть прямой печатью необработанных данных, полученных от PySerial. Если вы на самом деле получаете необработанные байты в виде 8-значных шестнадцатеричных значений, то:

#!python3
from binascii import unhexlify
data = b''.join(unhexlify(x)[::-1] for x in b'''\
68632057
62206A75
7A647261
B364206F
20616775
777A616E
616A2061
6A65696B
617A20B6
697A7970
6A65B361
70697020
77F36469
62202C79
6E647572
75206A65
7963696C
72656D75
6A616E20
73726F67
206A657A
65647572
77207972
73772065
00000069'''.splitlines())

print(data.decode('iso-8859-2'))

Выход:

W chuj bardzo długa nazwa jakiejś zapyziałej pipidówy, brudnej ulicyumer najgorszej rudery we wsi

Переводчик с польского на английский:

The dick very long name some zapyziałej Small Town , dirty ulicyumer worst hovel in the village

Ваш пример не работает, потому что вы пытались использовать str для хранения байтов. В Python 3 вы должны использовать byte строки.

На самом деле, если вы используете PySerial, вы все равно будете читать байтовые строки, которые вы можете преобразовать по мере необходимости:

with serial.Serial('/dev/ttyS1', 19200, timeout=1) as ser:
    s = ser.read(10)
    # Py3: s == bytes
    # Py2.x: s == str
    my_unicode_string = s.decode('iso-8859-2')

Если ваши данные iso-8895-2 на самом деле затем кодируются в шестнадцатеричное представление байтов ASCII, тогда вы должны применить дополнительный уровень кодирования:

with serial.Serial('/dev/ttyS1', 19200, timeout=1) as ser:
    hex_repr = ser.read(10)
    # Py3: hex_repr == bytes
    # Py2.x: hex_repr == str

    # Decodes hex representation to bytes
    # Eg. b"A3" = b'\xa3'
    hex_decoded = codecs.decode(hex_repr, "hex") 
    my_unicode_string = hex_decoded.decode('iso-8859-2')

Теперь вы можете передать my_unicode_string в вашу любимую библиотеку XML.

Эта тема закрыта. Рабочий код, который обрабатывает то, что нужно сделать:

x=177
x.to_bytes(1, byteorder='big').decode("ISO-8859-2")
Другие вопросы по тегам