如何配置pyodbc正确地接收使用freetds的unixODBC的和从SQL Server字符串?

2019-08-03 22:50发布

我无法从MSSQL服务器到蟒蛇一个有效的字符串。 我相信这是一个编码不一致的地方。 我相信这是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'\U0072006f\U006e0061\U00650067')

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

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)

使用T-SQL来执行相同的查询成绩单:

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
  • 2.2.14的unixODBC
  • 蟒蛇2.7.3
  • pyodbc 2.1.7-1(从Ubuntu的包)3.0.7-beta06(从源代码编译)

  • 服务器是XP与SQL Server Express 2008 R2

以下是在客户端上的几个配置文件的内容。

/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

Answer 1:

所以,经过不断的工作,我现在越来越Unicode字符转换为蟒。 不幸的是,我偶然发现的解决方案是关于接吻你表哥为满足。

我通过安装python3和python3-dev的包,然后用python3重建pyodbc解决了这个问题。

现在,我已经这样做了我的剧本现在的工作,即使我仍然Python 2.7版运行它们。

因此,我不知道什么是固定做这个,但它现在的作品,我可以继续,我开始与项目。



Answer 2:

你有一个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" ) )

我发现在该片段此页面 。



Answer 3:

如果您的pyodbc升级到3.0版本的问题将得到解决。



文章来源: How do I configure pyodbc to correctly accept strings from SQL Server using freeTDS and unixODBC?