Как pyodbc определяет кодировку? - PullRequest
3 голосов
/ 04 мая 2011

Я сражаюсь с Sybase SQL Anywhere 12 вместе с Python (и Twisted) уже несколько недель, и у меня даже все заработало.

Осталось только одно раздражение: если я запускаю свой скрипт на CentOS 5 с пользовательским Python 2.7.1, который является платформой развертывания, я получаю результаты в виде UTF-8 .

Если я запускаю его на своей коробке с Ubuntu (Natty Narwhal), я получаю их в latin1 .

Само собой разумеется, что я бы предпочел получать все свои данные в Юникоде, но суть этого вопроса не в этом. :)

Оба являются 64-битными блоками, оба имеют собственный Python 2.7.1. с UCS4 и специально созданным unixODBC 2.3.0.

Я в недоумении. Я не могу найти никакой документации по этому вопросу. Что заставляет pyodbc или unixODBC вести себя по-разному на двух компьютерах?

Неопровержимые факты:

  • Python: 2.7.1
  • БД: SQL Anywhere 12
  • unixODBC: 2.3.0 (2.2.14 действовал одинаково), самостоятельно скомпилирован с одинаковыми флагами
  • Драйвер ODBC: оригинал от Sybase.
  • CentOS 5 дает мне UTF-8, Ubuntu Natty Narwhal дает мне латынь1.

Мой файл odbc.ini выглядит так:

[sybase]
Uid             = user
Pwd             = password
Driver          = /opt/sqlanywhere/lib64/libdbodbc12_r.so
Threading       = True
ServerName      = dbname
CommLinks       = tcpip(host=the-host;DoBroadcast=None)

Я подключаюсь только с помощью DNS = 'sybase'.

ТИА!

Ответы [ 2 ]

4 голосов
/ 05 июля 2011

pyodbc использует спецификацию ODBC, которая поддерживает только 2 кодировки.Все функции ODBC, оканчивающиеся на 'W', являются версиями с широкими символами, использующими SQLWCHAR.Это определяется заголовками ODBC и обычно является UCS2, но иногда является UCS4.В нешироких версиях используется SQLCHAR и они всегда (?) Являются однобайтовыми ANSI / ASCII.

В ODBC нет абсолютно никакой поддержки кодировок с переменной шириной, таких как UTF8.Если драйверы ODBC предоставляют это, это абсолютно неправильно.Даже если данные хранятся в UTF8, драйвер должен конвертировать их в ANSI или UCS2.К сожалению, большинство драйверов ODBC совершенно неверны.

При отправке в драйвер pyodbc будет использовать ANSI, если данные являются объектом 'str', и будет использовать UCS2 / UCS4 (независимо от того, какой SQLWCHAR определен для вашей платформы)если данные являются объектом «Юникод».Драйверы определяют, являются ли данные SQLCHAR или SQLWCHAR при их возврате, и pyodbc не имеет права голоса в этом вопросе.Если это SQLCHAR, он преобразуется в объект 'str', а если SQLWCHAR преобразуется в объект 'Unicode'.

Это будет немного отличаться для версий 3.x, которые преобразуют как SQLCHAR, так и SQLWCHAR вЮникод по умолчанию.

4 голосов
/ 04 мая 2011

Я не могу сказать вам, почему это не так, но если вы добавите "Charset = utf-8" к своему DSN, вы должны получить желаемые результаты на обеих машинах.

Отказ от ответственности:Я работаю на Sybase в разработке SQL Anywhere.

...