资讯专栏INFORMATION COLUMN

Python-解决Cx_Oracle查询时UnicodeDecodeError的问题

Lsnsh / 1613人阅读

摘要:我们需要注意的是只有在数据库服务器端与客户端的编码一致的情况下我们才能正常的显示非编码而在中默认会将查询的字符串强制将其转换为。而正常的情况应该指定其编码为中国而设定就是相当于修改上述的编码为。

近期在项目中,要对1张100多万条记录的表进行查询,然后进行一些数据的统计,但是在这个过程中,发现只查询出来几条数据就出现了UnicodeDecodeError了。
在这里,我们使用sqlalchemy库进行查询,其内部还是Cx_Oracle来进行对应的操作,使用的Python版本为3.5.0,宿主系统为Windows 2008 Server,然后进行类似如下的操作:

from sqlalchemy import create_engine

engine = create_engine("oracle://demo:123456@192.168.1.202/TEST")
conn = engine.connect()
sql = "select t.type from TS t"
result = conn.execute(sql)
for row in result:
    print(row["type"])

在这里,我们首先创建1个到数据库的连接,然后进行对应的查询操作。很不幸的是,只查询不到10条记录就出现了1个UnicodeDecodeError错误了。
本来以为是数据库的服务器编码问题,因此在create_engine函数中追加了encoding参数,将其更改为:

engine = create_engine("oracle://demo:123456@192.168.1.202/TEST",encoding="UTF-8")

而另外1种可用的方式直接在连接路径中指定编码,类似如下:

engine = create_engine("oracle://demo:123456@192.168.1.202/TEST?charset=utf-8")

但是问题还是没有解决。在网上搜索了一下都没有找到适应的解决方案,突然想起来之前在使用Mysql数据库(个人喜欢Postgresql多一些)的时候,出现乱码的时候,我们常常会进行如下的操作:

set names gbk;

我们通过这种方式设置客户端的编码,而不是服务器端的编码,来解决终端下出现乱码的情况(由于Postgresql默认数据库就是UTF-8因此出现乱码的可能性较低)。而另外在Linux下安装Oracle的客户端时,设置了1个NLS_LANG的环境变量,详情可以参考Ubuntu14.04安装Oracle Instant Client这篇文章,当然这篇文章有一些细节的东西没有介绍。
一般情况下,我们在cmd中进行如下的设置:

setenv NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK

我们指定Oracle消息使用的语言为简体中文,而客户端的字符集为GBK。
另外,我们还可以执行如下的语句来确保上述的操作是正确的:

SELECT * FROM v$nls_parameters;

由于上述数据库服务器是部署在Windows上的,因此其结果自然为GBK,因此如果我们客户端使用UTF8字符集进行解码,自然而言会出现解码的错误。
我们需要注意的是,只有在数据库服务器端与客户端的编码一致的情况下,我们才能正常的显示非ASCII编码,而在sqlalchemy中默认会将查询的字符串强制将其转换为Unicode。因此类似Python3的如下过程:

>>> a="中国".encode("gbk")
>>> a
b"xd6xd0xb9xfa"

而在sqlalchemy中由于强制进行编码转换,因此类似执行如下的过程:

>>> a.decode("utf-8")
Traceback (most recent call last):
  File "", line 1, in 
UnicodeDecodeError: "utf-8" codec can"t decode byte 0xd6 in position 0: invalid continuation byte

因此就出现上述的问题了。而正常的情况应该指定其编码为GBK:

>>> a.decode("gbk")
"中国"

而设定NLS_LANG就是相当于修改上述的编码为GBK。

参考文章:

http://docs.oracle.com/cd/E12...
docs.sqlalchemy.org/en/latest/core/engines.html

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/38438.html

相关文章

  • python cx_Oracle基础使用方法

    摘要:使用的方法需要对格式进行控制,通过流获取这几个字段值不简洁个人观点。优点是能够使用的方法直接访问文件,不需要考虑打开关闭连接,并且通过流向文件中写入还挺好用的。要进行多个查询,个人建议使用完后将结果保留再关闭,多次查询重复该操作。 问题 使用python操作oracle数据库,获取表的某几个字段作为变量值使用。 使用Popen+sqlplus的方法需要对格式进行控制,通过流获取这几个字...

    dack 评论0 收藏0
  • Python中文编码问题

    摘要:使用中文替代中文中文编码中文编码中有以上两种声明字符串变量的方式,它们的主要区别是编码格式的不同,其中,的编码格式和文件声明的编码格式一致,而的编码格式则是。 字符串是Python中最常用的数据类型,而且很多时候你会用到一些不属于标准ASCII字符集的字符,这时候代码就很可能抛出UnicodeDecodeError: ascii codec cant decode byte 0xc4 ...

    Cheriselalala 评论0 收藏0

发表评论

0条评论

Lsnsh

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<