如何配置pyodbc以使用freeTDS和unixODBC正确接受来自SQL Server的字符串



我无法将MSSQL服务器中的有效字符串获取到python中。我认为某个地方的编码不匹配。我相信它介于ODBC层和python之间,因为我能够在tsql和isql中获得可读的结果。

pyodbc期望什么字符编码?我需要在链中更改什么才能使其工作?

具体示例

以下是一个简化的python脚本示例:

#!/usr/bin/env python
import pyodbc
dsn = 'yourdb'
user = 'import'
password = 'get0lddata'
database = 'YourDb'
def get_cursor():
con_string = 'DSN=%s;UID=%s;PWD=%s;DATABASE=%s;' % (dsn, user, password, database)
conn = pyodbc.connect(con_string)
return conn.cursor()
if __name__ == '__main__':
c = get_cursor()
c.execute("select id, name from recipe where id = 4140567")
row = c.fetchone()
if row:
print row

这个脚本的输出是:

(Decimal('4140567'), u'U0072006fU006e0061U00650067')

或者,如果脚本的最后一行更改为:

print "{0}, '{1}'".format(row.id, row.name)

那么结果是:

Traceback (most recent call last):
File "/home/mdenson/projects/test.py", line 20, in <module>
print "{0}, '{1}'".format(row.id, row.name)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

使用tsql执行相同查询的转录本:

root@luke:~# tsql -S cmw -U import -P get0lddata
locale is "C"
locale charset is "ANSI_X3.4-1968"
using default charset "UTF-8"
1> select id, name from recipe where id = 4140567
2> go
id      name
4140567 orange2
(1 row affected)

以及在isql:中

root@luke:~# isql -v yourdb import get0lddata
SQL>  select id, name from recipe where id = 4140567
+----------------------+--------------------------+
| id                   | name                     |
+----------------------+--------------------------+
| 4140567              | orange2                  |
+----------------------+--------------------------+
SQLRowCount returns 1
1 rows fetched

所以我已经做了一上午的工作,看起来很高很低,还没有弄清楚出了什么问题。

详细信息

以下是版本详细信息:

  • 客户端是Ubuntu 12.04
  • freetds v0.91
  • unixodbc 2.2.14
  • python 2.7.3
  • pyodbc 2.1.7-1(来自ubuntu包)&3.0.7-beta06(来源编译)

  • 服务器是带有SQL Server Express 2008 R2 的XP

以下是客户端上一些配置文件的内容。

/etc/freetds/freetds.conf

[global]
tds version = 8.0
text size = 64512
[cmw]
host = 192.168.90.104
port = 1433
tds version = 8.0
client charset = UTF-8

/etc/odbcinst.ini

[FreeTDS]
Description = TDS driver (Sybase/MS SQL)
Driver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so
Setup = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so
CPTimeout =
CPReuse =
FileUsage = 1

/etc/odbc.ini

[yourdb]
Driver = FreeTDS
Description = ODBC connection via FreeTDS
Trace = No
Servername = cmw
Database = YourDB
Charset = UTF-8

因此,经过持续的工作,我现在正在将unicode字符放入python中。不幸的是,我偶然发现的解决方案就像亲吻你的表妹一样令人满意。

我通过安装python3和python3dev包,然后用python3。

现在我已经完成了这项工作,我的脚本现在可以工作了,尽管我仍然使用python 2.7运行它们。

所以我不知道这样做修复了什么,但现在它有效了,我可以继续我开始的项目了。

您是否有可能在BOM(字节顺序标记)方面遇到问题?如果是这样的话,也许这段代码会有所帮助:

import codecs
if s.beginswith( codecs.BOM_UTF8 ):
# The byte string s begins with the BOM: Do something.
# For example, decode the string as UTF-8
if u[0] == unicode( codecs.BOM_UTF8, "utf8" ):
# The unicode string begins with the BOM: Do something.
# For example, remove the character.
# Strip the BOM from the beginning of the Unicode string, if it exists
u.lstrip( unicode( codecs.BOM_UTF8, "utf8" ) )

我在这个页面上找到了那个片段。

如果将pyodbc升级到版本3,问题就会得到解决。

相关内容

  • 没有找到相关文章

最新更新