Проблема с кодированием / декодированием строки — отсутствует символ с конца

#python #python-2.7 #encode #pyodbc #netezza

#python #python-2.7 #кодировать #pyodbc #netezza

Вопрос:

NVARCHAR В моей базе данных есть столбец типа. Я не могу преобразовать содержимое этого столбца в простую строку в своем коде. (Я использую pyodbc для подключения к базе данных).

 # This unicode string is returned by the database
>>> my_string = u'u4157u4347u6e65u6574u2d72u3430u3931u3530u3731u3539u3533u3631u3630u3530u3330u322du3130u3036u3036u3135u3432u3538u2d37u3134u3039u352d'

# prints something in chineese 
>>> print my_string
䅗䍇湥整⵲㐰㤱㔰㜱㔹㔳㘱㘰㔰㌰㈭㄰〶〶ㄵ㐲㔸ⴷㄴ〹㔭
  

Самое близкое, что я сделал, — это кодирование его utf-16 как:

 >>> my_string.encode('utf-16')
'xffxfeWAGCenter-04190517953516060503-20160605124857-4190-5'
>>> print my_string.encode('utf-16')
��WAGCenter-04190517953516060503-20160605124857-4190-5
  

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

 WAGCenter-04190517953516060503-20160605124857-4190-51
  

Я попытался закодировать его в utf-8 , utf-16 , ascii , utf-32 но, похоже, ничего не сработало.

У кого-нибудь есть идея относительно того, чего мне не хватает? И как получить желаемый результат из my_string .

Редактировать: при преобразовании его в utf-16-le я могу удалить ненужные символы из начала, но все же один символ отсутствует в конце

 >>> print t.encode('utf-16-le')
WAGCenter-04190517953516060503-20160605124857-4190-5
  

При попытке найти некоторые другие столбцы он работает. Что может быть причиной этой прерывистой проблемы?

Комментарии:

1. Вы видите метку порядка байтов (спецификация)

2. @brianpck Знак порядка байтов в начале пропущенный 1 в конце. Я сейчас расследую вопрос о метке порядка байтов . Есть идеи, почему 1 отсутствует в last?

3.Символы в my_string являются кодовыми точками cjk, так что вряд ли это будет то, что на самом деле возвращается из nvarchar поля? Если возможно, всегда можно прочитать его как a varchar с приведением select cast(field as varchar(xxx)) ...

4. Спецификация добавлена кодеком ‘utf-16’ и маловероятна в необработанных данных.

5. @AlexK. : Мой запрос похож SELECT UNIQUE(MY_ID) FROM MY_TABLE; и при печати resultset я получаю [(u'u4157u4347u6e65u6574u2d72u3430u3931u3530u3731u3539u3533u3631u3630u3530u3330u322du3130u3036u3036u3135u3432u3538u2d37u3134u3039u352d', )]

Ответ №1:

У вас серьезная проблема в определении вашей базы данных, в том, как вы храните в ней значения или в том, как вы считываете из нее значения. Я могу только объяснить, что вы видите, но ни почему, ни как это исправить без:

  • тип базы данных
  • способ ввода в него значений
  • способ извлечения значений для получения вашей псевдо-строки в юникоде
  • фактическое содержимое, если вы используете прямой (собственный) доступ к базе данных

То, что вы получаете, — это строка ASCII, где 8-битные символы сгруппированы по парам для построения 16-битных символов Юникода в порядке наименьшего конца. Поскольку ожидаемая строка содержит нечетное количество символов, последний символ был (безвозвратно) потерян при переводе, потому что исходная строка заканчивается на u'352d' где 0x2d — код ASCII для '-' и 0x35 для '5' . ДЕМОНСТРАЦИЯ:

 def cvt(ustring):
    l = []
    for uc in ustring:
        l.append(chr(ord(uc) amp; 0xFF)) # low order byte
        l.append(chr((ord(uc) >> 8) amp; 0xFF)) # high order byte
    return ''.join(l)

cvt(my_string)
'WAGCenter-04190517953516060503-20160605124857-4190-5'
  

Комментарии:

1. Я признаю, что это не отвечает на вопрос, но это лучшее, что я могу сделать с данной информацией, и это слишком подробно для комментария

2. Я использую Netezza в качестве ядра базы данных. и я не могу его закодировать ascii . Я настроил свой pyodbc для utf-16 . Дайте мне знать, какие дополнительные сведения вам нужны? Спасибо за объяснение. Я знаю, что что-то не так, но я не знаю, где проверить. Кроме того, эта база данных, которую я использую, принадлежит другой команде, я могу изменить конфигурацию только на уровне моего проекта.

3. @user7001260: не могли бы вы настроить pyodbc для кодировки latin1? Latin1 содержит только 256 первых кодов Юникода.

Ответ №2:

Проблема заключалась в том, что я использовал UTF-16 в своем odbcinst.ini файле where, поскольку мне приходилось использовать UTF-8 формат кодировки символов.

Ранее я менял его как OPTION параметр при подключении PyODBC . Но позже изменение его в odbcinst.ini файле устранило проблему.