繁体   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