Как pyodbc определяет кодировку?

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

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

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

Излишне говорить, что я бы предпочел, чтобы все мои данные были в Unicode, но суть этого вопроса не в этом. :)

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

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

Жесткие факты:

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

Мой 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'.

ТИА!


person hynek    schedule 04.05.2011    source источник


Ответы (2)


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

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

person Graeme Perrow    schedule 04.05.2011
comment
Спасибо! Работая там, не могли бы вы сделать sqlanydb потокобезопасным? ;) (-› stackoverflow.com/questions/5790435/ к настоящему времени у меня даже случаются сбои с pyodbc, по-видимому, Twisted вызывает что-то нехорошее в ваших драйверах) - person hynek; 04.05.2011
comment
Ну, я мог бы, но что я буду делать после обеда? - person Graeme Perrow; 05.05.2011
comment
Ну, ты мог бы решить проблему остановки и взять выходной на остаток дня? ;) - person hynek; 05.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 определен на вашей платформе), если данные являются объектом 'unicode'. Драйверы определяют, являются ли данные SQLCHAR или SQLWCHAR при их возврате, и pyodbc не имеет права голоса в этом вопросе. Если это SQLCHAR, он преобразуется в объект «str», а если SQLWCHAR преобразуется в объект «Unicode».

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

person mkleehammer    schedule 05.07.2011