Расшифровка байта с символами latin-1 в строку с десятичным представлением - PullRequest
4 голосов
/ 09 мая 2020

Я работаю над проектом миграции по обновлению уровня веб-сервера с python 2.7.8 до python 3.6.3, и в некоторых особых случаях я столкнулся с препятствием. Когда запрос получен от клиента, полезная нагрузка передается локально с помощью pyzmq, который теперь взаимодействует в bytes в python3 вместо str (как в python2).

Теперь полезная нагрузка, которую я получаю, закодирована с использованием схемы iso-8859-1 (latin-1) , и я могу легко преобразовать ее в строку как payload.decode ('latin-1') и передать его следующей службе ( sv c -save-entity ), которая ожидает строковый аргумент.

Однако последующая служба ' sv c -save-entity 'ожидает, что символы латинского алфавита (если они есть) будут представлены в справочнике символов ASCII (например, é для é), а не в шестнадцатеричном формате (например, \xe9 для é).

Я изо всех сил пытаюсь найти эффективный способ достичь этого преобразования. Может ли кто-нибудь python провести меня сюда? По сути, мне нужно определение функции, например, decode_tostring():

payload = b'Banco Santander (M\xe9xico)'         #payload is in bytes
payload_str = decode_tostring(payload)           #function to convert into string
payload_str == 'Banco Santander (México)'  #payload_str is a string in ASCII Character Reference

Определение decode_tostring(), пожалуйста. :)

1 Ответ

3 голосов
/ 09 мая 2020

Методы encode() и decode() принимают параметр с именем errors, который позволяет вам указать, как должны обрабатываться символы, которые не могут быть представлены в указанной кодировке. То, что вы ищете, - это замена ссылки на символы XML numeri c, которая, к счастью, является одним из стандартных обработчиков , предоставляемых в модуле codecs.

Теперь это a little сложный, чтобы фактически выполнить замену так, как вы хотите, потому что операция замены символов, отличных от ASCII, соответствующими ссылками на символы XML numeri c происходит во время кодирования, а не декодирование. В конце концов, кодирование - это процесс, который принимает символы и испускает байты, поэтому только во время кодирования вы можете определить, есть ли у вас символ, не являющийся частью ASCII. Самый чистый способ, который я могу придумать на данный момент для получения желаемого преобразования, - это декодировать, перекодировать и повторно декодировать, применяя замену ссылки на сущность XML на этапе кодирования.

def decode_tostring(payload):
    return payload.decode('latin-1').encode('ascii', errors='xmlcharrefreplace').decode('ascii')

Я не удивлюсь, если где-то есть метод, который заменит все символы, отличные от ASCII, в строке на их XML numeri c ссылки на символы и вернет вам строку, и если да, вы могли бы используйте его для замены кодировки и второго декодирования. Но я не знаю ни одного. Ближайшим, что я нашел на данный момент, был xml.sax.saxutils.escape(), но он действует только на определенные c символы.


Это не имеет отношения к вашему основному вопросу, но я хотел прояснить одну вещь: объекты numeri c, такие как é, являются особенностями SGML, HTML и XML, которые являются языками разметки - способом представления структурированных данные как текст. Они не имеют ничего общего с ASCII. Кодировка символов, такая как ASCII, представляет собой не что иное, как таблицу некоторых символов и некоторых последовательностей байтов, так что каждый символ в таблице отображается на одну последовательность байтов в таблице и наоборот, с некоторыми ограничениями, чтобы сделать сопоставление однозначным.

Если у вас есть строка с символами, которых нет в конкретной таблице кодировки, вы не можете закодировать строку, используя эту кодировку. Но вы можете преобразовать строку в новую строку, заменив символы, которых нет в таблице, последовательностями символов, которые равны в таблице, а затем закодировать новая строка. Есть много способов выполнить замену, например, XML numeri c ссылки на сущности. Некоторые из других обработчиков ошибок в модуле Python codecs представляют другие подходы к этой замене.

...