簡體   English   中英

Python和IBM DB2:UnicodeDecodeError

[英]Python and IBM DB2: UnicodeDecodeError

我收到此錯誤消息

UnicodeDecodeError:'ascii'編解碼器無法解碼位置38中的字節0xc8:序數不在范圍內(128)

當我嘗試在Python中執行任何sql查詢時,像這樣:

>>> import ibm_db
>>> conn = ibm_db.connect("sample","root","root")
>>> ibm_db.exec_immediate(conn, "select * from act")

我檢查了默認編碼,似乎是'utf8':

>>> import sys
>>> sys.getdefaultencoding()
'utf-8'

我也知道這個帖子,人們在討論類似的問題。 其中一個建議是:

您是否已應用所需的數據庫PTF(7.1和SI57146的SI57014和SI57015以及7.2的SI57147)? 它們作為distreq包含在內,因此它們應與您的PTF保持一致,但不會自動應用。

但是,我不知道什么是數據庫PTF以及如何應用它。 需要幫忙。

PS。 我正在使用Windows 10。

編輯

這是我收到錯誤消息的方式:

>>> print(ibm_db.stmt_errormsg())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc8 in position 38:    
ordinal not in range(128)

但是當我在DB2 CLP運行相同的查詢“select * from act”時,它就可以了。 這是驅動程序信息,我在Python中運行此代碼:

if client:
    print("DRIVER_NAME: string(%d) \"%s\"" % (len(client.DRIVER_NAME), client.DRIVER_NAME))
    print("DRIVER_VER: string(%d) \"%s\"" % (len(client.DRIVER_VER), client.DRIVER_VER))
    print("DATA_SOURCE_NAME: string(%d) \"%s\"" % (len(client.DATA_SOURCE_NAME), client.DATA_SOURCE_NAME))
    print("DRIVER_ODBC_VER: string(%d) \"%s\"" % (len(client.DRIVER_ODBC_VER), client.DRIVER_ODBC_VER))
    print("ODBC_VER: string(%d) \"%s\"" % (len(client.ODBC_VER), client.ODBC_VER))
    print("ODBC_SQL_CONFORMANCE: string(%d) \"%s\"" % (len(client.ODBC_SQL_CONFORMANCE), client.ODBC_SQL_CONFORMANCE))
    print("APPL_CODEPAGE: int(%s)" % client.APPL_CODEPAGE)
    print("CONN_CODEPAGE: int(%s)" % client.CONN_CODEPAGE)
    ibm_db.close(conn)
else:
    print("Error.")

它打印:

DRIVER_NAME: string(10) "DB2CLI.DLL"
DRIVER_VER: string(10) "10.05.0007"
DATA_SOURCE_NAME: string(6) "SAMPLE"
DRIVER_ODBC_VER: string(5) "03.51"
ODBC_VER: string(10) "03.01.0000"
ODBC_SQL_CONFORMANCE: string(8) "EXTENDED"
APPL_CODEPAGE: int(1251)
CONN_CODEPAGE: int(1208)
True

編輯

我也試過這個:

>>> cnx = ibm_db.connect("sample","root","root")
>>> query = "select * from act"
>>> query.encode('ascii')
b'select * from act'
>>> ibm_db.exec_immediate(cnx, query)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Exception
>>> print(ibm_db.stmt_errormsg())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc8 in position 38: 
ordinal not in range(128)

如您所見,在這種情況下,我也得到了相同的錯誤消息。

摘要

以下是我的所有觀點:

C:\Windows\system32>chcp
Active code page: 65001

C:\Windows\system32>python
Python 3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 20:20:57) [MSC v.1600 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import ibm_db
>>> cnx = ibm_db.connect("sample","root","root")
>>> ibm_db.exec_immediate(cnx, "select * from act")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Exception
>>> print(ibm_db.stmt_errormsg())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc8 in position 38: ordinal not in range(128)
>>> ibm_db.exec_immediate(cnx, b"select * from act")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Exception: statement must be a string or unicode
>>> query = "select * from act"
>>> query = query.encode()
>>> ibm_db.exec_immediate(cnx, query)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Exception: statement must be a string or unicode
>>> ibm_db.exec_immediate(cnx, "select * from act").decode('cp-1251')
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
Exception

您在此處擁有的是客戶端代碼(ibm_db)與DB2服務器之間的不兼容性。 正如您在客戶端代碼中看到的,查詢的邏輯基本上是:

  1. 提取並檢查傳入的參數(第4873至4918行)。
  2. 為查詢分配本機對象(最多4954)。
  3. 進行查詢並解碼結果(函數的其余部分)。

根據我們到目前為止的調查,您知道您為查詢傳入的數據格式正確(因此不是第1步)。 查看步驟2中的錯誤路徑,您將看到解釋這些故障的簡單錯誤消息。 因此,你在第3步失敗了。

您在查詢中引發了一個空的異常,當您嘗試獲取錯誤的詳細信息時,您將獲得另一個Unicode解碼異常。 這看起來像是ibm_db中的錯誤或配置錯誤,這意味着您的DB2安裝不兼容。 那我們怎樣才能找出哪個......?

如其他地方所述,問題基本上與代碼頁有關。 所有的ibm_db代碼基本上都將字符串解釋為ASCII(通過將它們轉換為StringOBJ_FromASCII ,它們向下映射到Python API,這些API堅持接收ASCII字符 - 如果沒有則會拋出unicode異常)。

根據您的診斷,您可以嘗試通過安裝/配置您的系統(客戶端和DB2服務器)來使用美國英語來證明/反駁此問題。 這應該讓你通過代碼頁不兼容,在這里找到真正的錯誤。

如果查詢實際上是通過網絡進行的,您可能只是獲得一個網絡跟蹤,顯示從服務器返回的響應。 然而,基於您在日志中沒有看到任何內容的事實,我不相信這會帶來任何成果。

如果你不需要修補ibm_db代碼來處理非ASCII內容 - 無論是通過維護者提出錯誤報告還是自己嘗試(如果你知道如何構建和調試C擴展)。

問題是DB2服務器在配置輸出中返回CP-1251(也稱為Windows-1251)文本(由APPL_CODEPAGE: int(1251)證明)。 Python(特別是交互式Python REPL)期望UTF-8或ASCII輸出,因此這會導致問題。

解決方案是:

ibm_db.exec_immediate(conn, "select * from act").decode('cp-1251')

此外,您需要確保終端的文本編碼設置為UTF-8。 有關更改該設置的詳細信息取決於您使用的特定終端。 由於您已經說過使用cmd ,因此相應的命令是chcp 65001

在這種情況下,使用utf8環境,需要一個ascii的東西; 我使用解碼方法。

'ascii' codec can't decode byte 0xc8 

好吧,這是正常的,這不是ascii而是utf8字符串:你應該用utf8編碼解碼它。

...  
query.decode('utf8')  
ibm_db.exec_immediate(cnx, query)

之后,您可能需要重新編碼結果以進行寫入或打印。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM