我正在编写一个读取CSV的Python脚本,使用cx_Oracle将内容写入Oracle数据库。到目前为止,我一直收到以下错误:
UnicodeEncodeError: 'ascii' codec can't encode character '\xa0' in position 1369: ordinal not in range(128)
显然,cx_Oracle正在尝试将Unicode字符转换为ASCII,但它无效。
一些澄清要点:
open('all.csv', encoding='utf8')
NVARCHAR2
字段表示文字,NLS_NCHAR_CHARACTERSET
设置为AL16UTF16
。 NLS_CHARACTERSET
为WE8MSWIN1252
,但据我所知,由于我使用的是NVARCHAR2
,因此不应该具有相关性。NLS_LANG
环境变量设置为每this post .AL16UTF16
,_.AL16UTF16
和AMERICAN_AMERICA.WE8MSWIN1252
之类的内容,但我仍然可以同样的错误。鉴于我正在读取UTF-8文件并尝试写入Unicode编码表,有人能想到为什么cx_Oracle仍会尝试将我的数据转换为ASCII吗?
我能用这段代码产生错误:
field_map = {
...
}
with open('all.csv', encoding='utf8') as f:
reader = csv.DictReader(f)
out_rows = []
for row in reader:
if i == 1000:
break
out_row = {}
for field, source_field in field_map.items():
out_val = row[source_field]
out_row[field] = out_val
out_rows.append(out_row)
i += 1
out_db = datum.connect('oracle-stgeom://user:pass@db')
out_table = out_db['service_requests']
out_table.write(out_rows, chunk_size=10000)
datum
模块是我正在研究的数据抽象库。负责写入Oracle表的函数位于here。
完整的追溯是:
File "C:\Projects\311\write.py", line 64, in <module>
out_table.write(out_rows, chunk_size=10000)
File "z:\datum\datum\table.py", line 89, in write
self._child.write(rows, from_srid=from_srid, chunk_size=chunk_size)
File "z:\datum\datum\oracle_stgeom\table.py", line 476, in write
self._c.executemany(None, val_rows)
UnicodeEncodeError: 'ascii' codec can't encode character '\xa0' in position 1361: ordinal not in range(128)
答案 0 :(得分:1)
检查连接上“encoding”和“nencoding”属性的值。通过调用检查环境变量NLS_LANG和NLS_NCHAR的OCI例程来设置此值。看起来这个值是US-ASCII或等价的。写入数据库时,cx_Oracle接受文本并通过Oracle客户端期望的编码中的编码获取字节字符串。请注意,这与数据库编码无关。一般来说,为了获得最佳性能,最好匹配数据库和客户端编码 - 但如果不这样做,Oracle将很乐意在两者之间进行转换,前提是所有使用的字符都可以在两个字符集中表示!
请注意,如果NLS_LANG的值无效,则基本上会被忽略。 AL16UTF16就是这样一个无效的条目!因此,将其设置为您想要的值(例如.UTF8)并检查连接上的编码和编码值,直到获得所需的值。
另请注意,除非另有说明,否则假定通过cx_Oracle绑定到数据库的所有字符串都采用正常编码,而不是NCHAR编码。您可以使用cursor.setinputsizes()并指定输入类型为NCHAR,FIXED_NCHAR或LONG_NCHAR来覆盖它。