用python的pymssql模塊讀取舊業務系統後臺SQL Server 2000數據庫展現數據爲亂碼html
數據庫的[rooms]表記錄一些功能房間列表,與其餘接口數據進行對比,而後輸出對比結果。python
rooms表結構:sql
CREATE TABLE [rooms] ( [id] [int] IDENTITY (1, 1) NOT NULL , [name] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL , PRIMARY KEY CLUSTERED ([id] ON [PRIMARY] , UNIQUE NONCLUSTERED ([des]) ON [PRIMARY] ) ON [PRIMARY] GO
模擬代碼數據庫
# -*- coding: utf-8 -*- import pymssql rooms=None with pymssql.connect(host='192.168.1.100',database='builds', user='sa',password='password', # charset='utf8', ) as conn: cur=conn.cursor() sql="select id,name from rooms" cur.execute(sql) rooms=cur.fetchall() if rooms and isinstance(rooms,(list,tuple)): for room_id,room_name in rooms: print "\t".join([str(room_id),room_name])
在通用環境中運行代碼,room_name變量列顯示亂碼windows
# 注意此時輸出標記爲u,說明識別爲unicode編碼,正常時此時print出是真實值 >>> room_name u'\xbf\xec\xb5\xdd\xbc\xe4\xa3\xa8\xc3\xc5\xc4\xda\xa3\xa9' # 打印原始值爲亂碼,因此懷疑實際存儲的是被標記爲unicode的其餘編碼 >>> print room_name ¿ìµÝ¼ä£¨ÃÅÄÚ£© # 這時能夠將引號內賦值,再使用chardet.detect()判斷 >>> aa='\xbf\xec\xb5\xdd\xbc\xe4\xa3\xa8\xc3\xc5\xc4\xda\xa3\xa9' >>> aa '\xbf\xec\xb5\xdd\xbc\xe4\xa3\xa8\xc3\xc5\xc4\xda\xa3\xa9' # 果真,檢測出的結果是GB2312編碼 >>> chardet.detect(aa) {'confidence': 0.99, 'encoding': 'GB2312'} # 輸出正常 >>> print aa.decode('gb2312') 快遞間(門內) # 此時,須要unicode->encode('Latin1')->decode('GB2312') >>> room_name.encode('latin1').decode('GB2312') u'\u5feb\u9012\u95f4\uff08\u95e8\u5185\uff09' >>> print room_name.encode('latin1').decode('GB2312') 快遞間(門內)
pymssql基礎實現使用的是cpython,從GitHub的官方代碼文件_mssql.pyx,能夠看到一些處理過程。使用strcpy函數對數據交換,由於對cpython不瞭解,懷疑是在處理雙字節文字轉碼時的一點bug。ide
這個問題有兩個解決辦法:函數
print "\t".join([str(room_id),room_name.encode('latin1').decode('gbk')])
[room_name] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL
原文:這裏工具
參考:post
1)"UnicodeDecodeError: ‘gbk’ codec can’t decode bytes in position 2-3: illegal multibyte sequence"開發工具