Python, как я могу правильно печатать cp1258 вьетнамских символов? - PullRequest
2 голосов
/ 01 ноября 2019

Как правильно печатать вьетнамские cp1258 закодированные символы в python 3? Кажется, проблема не в моем терминале, поскольку он правильно напечатает первый оператор print в моем коде. Я пытаюсь декодировать шестнадцатеричные символы на вьетнамский

Код:

import binascii

data = 'tạm biệt'
print(data) # tạm biệt

a = binascii.hexlify(data.encode('cp1258', errors='backslashreplace'))
print(a) # b'745c75316561316d2062695c753165633774'
# if i dont use the error handler here, then I get a UnicodeEncodeError for \u1ea1

print(
    binascii.unhexlify(a).decode('cp1258') # t\u1ea1m bi\u1ec7t
)

Ответы [ 2 ]

2 голосов
/ 01 ноября 2019

Кажется, что в Python отсутствует поддержка кодовой страницы 1258 . Устаревший кодек поддерживает вьетнамский язык путем объединения диакритических знаков, но Python не знает, как преобразовать Unicode в эти комбинации. Полагаю, вам придется выполнить свое собственное преобразование.

В качестве первого шага обратите внимание, что unicodedata.normalize('NFD', data) разбивает представление на базовый символ и последовательность сочетаний диакритических знаков.

>>> unicodedata.normalize('NFD', data).encode('utf-8')
b'ta\xcc\xa3m bie\xcc\xa3\xcc\x82t'
>>> '{0:04x}'.format(ord(b'\xcc\xa3'.decode('utf-8')))
'0323'

Таким образом, U + 0323 является объединяющим диакритическим знаком Unicode для точки-under, и это соответствие должно быть известно кодеку (на странице Википедии, на которую я ссылаюсь выше, показан тот же код символа Unicode для кодовой точки CP1258 0xF2).

Я не знаю достаточно о целевом кодеке, чтобы сказать вам, как сопоставить их с CP1258, но если вам повезет, уже есть своего рода отображение этих вКодек Python.

iconv на моем Mojave MacOS, кажется, преобразует это без заминки:

$ iconv -t cp1258 <<<'tạm biệt' | xxd
00000000: 7461 f26d 2062 69ea f274 0a              ta.m bi..t.

Из этого выглядит, что диакритический знак применяется просто как суффикс - 61 равно a, и, как отмечено выше, f2 - это объединяющая диакритика для размещения точки под основным глифом.

Если у вас есть рабочий iconv, быстрый и грязный обходной путь можетбыть, чтобы запустить его как subprocess.

import subprocess

converted = subprocess.run(['iconv', '-t', 'cp1258'],
    input=data.encode('utf-8'), stdout=subprocess.PIPE).stdout

Если мое понимание верно, это действительно должно быть сообщено как ошибка в Python. Он определенно должен знать, как совершать обходы между этим кодеком и Unicode, если он хочет заявить, что поддерживает его.

0 голосов
/ 01 ноября 2019

Я понял это. Декодирование с unicode-escape делает свое дело.

import binascii

data = u'tạm biệt'
print(data) # tạm biệt

a = binascii.hexlify(data.encode('cp1258', errors='backslashreplace'))
print(a) # b'745c75316561316d2062695c753165633774'
# if i dont use the error handler here, then I get a UnicodeEncodeError for \u1ea1

print(
    binascii.unhexlify(a).decode('unicode-escape') # tạm biệt
)
...