Python переводит байт-код в utf-8 с помощью переменной

У меня есть следующая проблема:

Из базы данных SQL Server я читаю данные, используя модуль Python pypyodbc и драйвер ODBC 13 для SQL Server, и записываю их в текстовые файлы.

База данных содержит все виды специальных символов, и они читаются как:

'PR\xc3\x86KVAL'

Часть '\xc3\x86' представляет собой байт-код и должна интерпретироваться таким образом. Остальные символы следует интерпретировать, как показано. UTF8 переведет '\xc3\x86' в Æ.

Если я ввожу значение в b'PR\xc3\x86KVAL' , python распознает его как байт-код, и я могу преобразовать его в PRÆKVAL. Смотри ниже:

s = b'PR\xc3\x86KVAL'
print(s)
bb = s.decode('utf-8')
print(bb)

Проблема в том, что я не знаю, как заставить 'PR\xc3\x86KVAL’ распознаваться как объект байт-кода.

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

Я тоже пробовал ast.literal_eval(r”b'PR\xc3\x86KVAL'”), но переменные так работать не будут.


person Marc Enthoven    schedule 10.04.2018    source источник


Ответы (1)


Поскольку вы начинаете с PR\xc3\x86KVAL как текстовой строки, а decode действительно ожидает необработанную последовательность байтов, вам необходимо преобразовать текстовую строку в объект bytes. Но при преобразовании из одного значения «кодировки» в другое Python должен знать, с какой кодировки он начинается!

Самый простой способ сделать это — явно кодировать строку, используя кодировку, которая не изменяет специальные символы. Вы должны быть осторожны, потому что вполне возможно, что код символа может быть переведен во что-то другое, что уничтожит их значение.

Вы можете видеть это на простом примере: попытка сообщить Python, что это должен быть простой код ASCII, терпит неудачу по очевидной причине.

>>> s = 'PR\xc3\x86KVAL'.encode('ascii')
UnicodeEncodeError: 'ascii' codec can't encode characters in position 2-3: ordinal not in range(128)

Несмотря на то, что в стеке более 1000 вопросов. Overflow об этом, причина сбоя должна быть легко понятна. Все, что делает пара кодировщик/декодер, — это переводит каждый символ из «источника» в «назначение». Это может работать только в том случае, если рассматриваемый символ действительно существует как в исходной, так и в целевой кодировках. Предположим, вы хотите перевести греческий символ β в русский б, тогда источник должен уметь декодировать греческий символ (потому что именно так вы его ввели), а пункт назначения должен< /em> уметь кодировать русский символ.

Таким образом, вы должны быть осторожны, чтобы выбрать кодировку, которая не меняет символ \x86 в вашей строке ввода на Ж (что было бы, например, при использовании cp866).

К счастью, как указано в https://stackoverflow.com/a/2617930/2564301, существует кодировка, которая не испортить вещи:

Передайте data.decode('latin1') кодеку. latin1 сопоставляет байты 0–255 с символами Unicode 0–255, что довольно элегантно.

и так это должно работать:

>>> s = 'PR\xc3\x86KVAL'.encode('latin1')
>>> print(s)
b'PR\xc3\x86KVAL'

Теперь s — это правильно закодированный объект byte, поэтому вы можете декодировать его по своему усмотрению:

>>> bb = s.decode('utf-8')
>>> print(bb)
PRÆKVAL

Сделанный!

person Jongware    schedule 10.04.2018