pyodbc如何确定编码?

时间:2011-05-04 13:53:51

标签: python pyodbc sqlanywhere unixodbc

到目前为止,我正在与Python(和Twisted)一起对抗Sybase SQL Anywhere 12几周,我甚至让我的东西工作。

只剩下一个烦恼:如果我使用自定义Python 2.7.1(部署平台)在CentOS 5上运行我的脚本,我的结果为 UTF-8

如果我在我的Ubuntu盒子(Natty Narwhal)上运行它,我会在 latin1 中获取它们。

毋庸置疑,我更愿意用Unicode获取所有数据,但这不是问题的重点。 :)

两者都是64位盒子,都有自定义Python 2.7.1。使用UCS4和自定义构建的unixODBC 2.3.0。

我在这里不知所措。我找不到任何相关的文档。是什么让pyodbc或unixODBC在两个盒子上表现不同?

事实真相:

  • Python:2.7.1
  • DB: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'连接。

TIA!

2 个答案:

答案 0 :(得分:4)

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

免责声明:我在SQL Anywhere工程中为Sybase工作。

答案 1 :(得分: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。

相关问题