3

到目前为止,我正在与 Python(和 Twisted)一起使用 Sybase SQL Anywhere 12 数周,我什至让我的东西正常工作。

只剩下一个烦恼:如果我在 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 无处不在 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' 进行连接。

蒂亚!

4

2 回答 2

4

pyodbc 使用 ODBC 规范,它只支持 2 种编码。所有以“W”结尾的 ODBC 函数都是使用 SQLWCHAR 的宽字符版本。这由 ODBC 标头定义,通常为 UCS2,但偶尔为 UCS4。非宽版本使用 SQLCHAR 并且总是(?)单字节 ANSI/ASCII。

ODBC 中绝对不支持可变宽度编码,例如 UTF8。如果 ODBC 驱动程序提供了它,那是绝对不正确的。即使数据以 UTF8 存储,也必须由驱动程序将其转换为 ANSI 或 UCS2。不幸的是,大多数 ODBC 驱动程序完全不正确。

发送到驱动程序时,如果数据是“str”对象,pyodbc 将使用 ANSI,如果数据是“unicode”对象,则将使用 UCS2/UCS4(在您的平台上定义的任何 SQLWCHAR)。驱动程序在返回数据时确定数据是 SQLCHAR 还是 SQLWCHAR,pyodbc 对此没有任何发言权。如果是 SQLCHAR,则将其转换为“str”对象,如果 SQLWCHAR 将转换为“unicode”对象。

这对于 3.x 版本会略有不同,默认情况下会将 SQLCHAR 和 SQLWCHAR 都转换为 Unicode。

于 2011-07-05T18:52:19.260 回答
4

我不能告诉你为什么它不同,但是如果你将“Charset=utf-8”添加到你的 DSN,你应该在两台机器上都得到你想要的结果。

免责声明:我在 Sybase 的 SQL Anywhere 工程部门工作。

于 2011-05-04T17:00:57.637 回答