python - 无法使用 cx_Oracle 写入 Unicode 文本

标签 python oracle unicode utf-8 cx-oracle

我正在编写一个Python脚本,该脚本读取CSV并使用cx_Oracle将内容写入Oracle数据库。到目前为止,我遇到了以下错误:

UnicodeEncodeError: 'ascii' codec can't encode character '\xa0' in position 1369: ordinal not in range(128)

显然,cx_Oracle 正在尝试将 Unicode 字符转换为 ASCII,但它不起作用。

一些澄清点:

  • 我使用的是 Python 3.4.3
  • CSV 文件采用 UTF-8 编码,打开方式如下:open('all.csv',encoding='utf8')
  • 我在数据库中使用 NVARCHAR2 字段作为文本,并且 NLS_NCHAR_CHARACTERSET 设置为 AL16UTF16NLS_CHARACTERSETWE8MSWIN1252,但据我了解,这应该不相关,因为我使用的是 NVARCHAR2
  • 我尝试将 NLS_LANG 环境变量设置为 .AL16UTF16_.AL16UTF16AMERICAN_AMERICA.WE8MSWIN1252this post ,但我仍然遇到同样的错误。

鉴于我正在读取 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)

最佳答案

检查连接上“encoding”和“nencoding”属性的值。该值是通过调用检查环境变量 NLS_LANG 和 NLS_NCHAR 的 OCI 例程来设置的。看起来这个值是 US-ASCII 或等效值。当写入数据库时​​,cx_Oracle 获取文本并通过以 Oracle 客户端期望的编码进行编码来获取字节字符串。请注意,这与数据库编码无关。一般来说,为了获得最佳性能,最好匹配数据库和客户端编码 - 但如果不这样做,Oracle 会很乐意在两者之间进行转换,前提是所使用的所有字符都可以在两个字符集中表示!

请注意,如果 NLS_LANG 的值无效,则它实际上会被忽略。 AL16UTF16 就是这样一个无效条目!因此,将其设置为您想要的值(例如.AL32UTF8)并检查连接上的encoding和nencoding的值,直到获得您想要的值。

另请注意,除非另有说明,否则所有通过 cx_Oracle 绑定(bind)到数据库的字符串均假定采用正常编码,而不是 NCHAR 编码。您可以使用cursor.setinputsizes() 并指定输入类型为NCHAR、FIXED_NCHAR 或LONG_NCHAR 来覆盖此设置。

关于python - 无法使用 cx_Oracle 写入 Unicode 文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37574647/

相关文章:

java - 如何运行 oracle 客户端服务器教程?

javascript - 哪些字符与 Array.from 分组?

Perl - 将 PC UTF-8 转换为 PC ANSI

python - 如何将 QLabel 文本与标签的右边缘对齐

python - 如何使用 matplotlib 将元数据添加到 Windows 10 中轻松出现的图像

python - Unicode编码错误: 'charmap' codec can't encode character '\u5347' in position 68: character maps to <undefined>

python - 将一个时间序列的数据分布到另一个时间序列上

oracle - Oracle 包中的最大行数

sql - WPF比较两个数据表以查找匹配值

c++ - 模板和字符串文字和 UNICODE