到目前为止,我正在与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在两个盒子上表现不同?
事实真相:
我的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!
答案 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。