6

MSSQLサーバーからPythonに有効な文字列を取得できません。どこかにエンコーディングの不一致があると思います。tsqlとisqlで読み取り可能な結果を​​取得できるため、ODBCレイヤーとPythonの間にあると思います。

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)

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

だから私は朝にこれで働き、高くも低くも見え、何が悪いのか理解していませんでした。

詳細

バージョンの詳細は次のとおりです。

  • クライアントはUbuntu12.04です
  • freetds v0.91
  • unixodbc 2.2.14
  • Python 2.7.3
  • pyodbc 2.1.7-1(ubuntuパッケージから)&3.0.7-beta06(ソースからコンパイル)

  • サーバーは、SQL Server Express2008R2を搭載した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
4

3 に答える 3

2

そのため、作業を続けた後、ユニコード文字をPythonに取り込んでいます。残念ながら、私が見つけた解決策は、あなたのいとこにキスをするのと同じくらい満足のいくものです.

python3 および python3-dev パッケージをインストールしてから、python3 で pyodbc を再構築することで問題を解決しました。

これを行ったので、まだ Python 2.7 でスクリプトを実行しているにもかかわらず、スクリプトが機能するようになりました。

これにより何が修正されたのかはわかりませんが、現在は機能しており、開始したプロジェクトに進むことができます。

于 2012-12-18T19:55:06.153 に答える
1

BOM(Byte Order Marker)に問題がある可能性はありますか?もしそうなら、多分このコードスニペットは役立つでしょう:

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" ) )

このページでそのスニペットを見つけました。

于 2012-12-12T00:19:20.620 に答える