UnicodeEncodeError: 'ascii'编解码器无法在位置54处编码字符u'\xe9',该字符超出了128个字符的范围。

4

我知道这个问题已经被问过很多次了,但是没有一个答案能够给我解决方案。

这里是代码(Python 2.7):

import cx_Oracle
import pandas as pd

connstr = 'MyConstr'
conn = cx_Oracle.connect(connstr)
cur = conn.cursor()

xl = pd.ExcelFile("C:\\TEMP\\for_kkod.xlsx")
df = xl.parse(0)

for i in df.index:
    s = u"insert into MY_TABLE values({0}, '{1}')".format(int(df.iloc[i]['kkod']), df.iloc[i]['kkodnev'])
    print s
    print type(s)
    cur.execute(s)

这两个打印的结果如下:
insert into MY_TABLE values(10, 'Készítés')
<type 'unicode'>

您可以看到,s的类型是unicode,但我仍然收到了此错误消息:

UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 54: ordinal not in range(128)

我尝试了各种可能的方式,包括使用和不使用u""、编码和解码等,但仍然出现相同的错误消息。你有什么想法吗?

你会收到一个编码错误,因为cur.execute()需要一个字节串。 - Martijn Pieters
是的,但我的第一次尝试是这样的:cur.execute("insert into MYTABLE values(%s, %s)", (int(df.iloc[i]['kkod']), df.iloc[i]['kkodnev']))。 - Gabor
2个回答

4
您正在向 cursor.execute() 提供 Unicode SQL 语句。该方法只能接受 字节字符串 SQL 语句
您不应使用字符串插值将 Unicode 值插入到 SQL 查询中(它本身仅为 ASCII)。始终使用查询参数!
 s = "insert into MY_TABLE values(:0, :1)"
 cur.execute(s, (int(df.iloc[i]['kkod']), df.iloc[i]['kkodnev']))

现在要插入的值作为参数传递,并由数据库适配器负责正确编码这些值(以及适当地转义这些值以避免 SQL 注入问题)。
上述示例使用数字(位置)参数,您还可以使用命名参数,在字典中传递具有相匹配键的值。
 s = "insert into MY_TABLE values(:kkod, :kkodnev)"
 cur.execute(s, {'kkod': int(df.iloc[i]['kkod']), 'kkodnev': df.iloc[i]['kkodnev']})

您需要确保您的连接和表列正确配置以处理Unicode。例如,您需要设置NLS_LANG选项:

import os
os.environ['NLS_LANG'] = '.AL32UTF8'

仍然不起作用。我有这个:s =“insert into MYTABLE values(:kkod,:kkodnev)”print type(s)是:<type 'str'>和exec:cur.execute(s,{'kkod':int(df.iloc [i] ['kkod']),'kkodnev':df.iloc [i] ['kkodnev']}),但是相同的错误消息:UnicodeEncodeError:'ascii'编解码器无法在位置11处编码字符u'\ xe9':序数不在范围内128 - Gabor
@Gabor:首先,确保回溯包括cursor.execute()行。也许将参数字典定义移到单独的一行(params = {'kkod': int(df.iloc[i]['kkod']), 'kkodnev': df.iloc[i]['kkodnev']}, cur.execute(s, params)),并验证回溯仍然指责cur.execute()调用。然后验证您的数据库列是否具有存储Unicode的正确类型,例如NVARCHAR2。对于您来说,NLS_LANG设置为什么? - Martijn Pieters
追踪(Traceback)最近的一次调用: 文件“oracle_insert.py”,第15行,在<module>中: cur.execute(s, {'kkod': int(df.iloc[i]['kkod']), 'kkodnev': df.iloc[i]['kkodnev']}) UnicodeEncodeError: 'ascii'编解码器无法在第11个位置编码字符u'\xe9':该编码值不在128的范围内。 - Gabor
但是这个设置是在连接时设置的吗? - Martijn Pieters
1
我明白了!我忘了在代码中加入你建议的以下代码行os.environ['NLS_LANG'] = '.AL32UTF8'。现在已经添加了,而且它正在工作!非常感谢! - Gabor
显示剩余3条评论

-1

只需使用以下参数进行连接:

connection = cx_Oracle.connect(connectString, encoding="UTF-8",nencoding="UTF-8")


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接