【问题标题】:Writing accented characters to Oracle将重音字符写入 Oracle
【发布时间】:2013-01-21 22:14:16
【问题描述】:

我必须更新现有脚本,以便将一些数据写入 Oracle 10g 数据库。脚本和数据库都在同一台 Solaris 10 (Intel) 机器上运行。 Python 是 v2.4.4。

我正在使用 cx_Oracle 并且可以毫无问题地读取/写入数据库。但是我正在编写的数据包含未正确写入的重音字符。重音字符变成一个倒置的问号。

使用此代码从二进制文件中读取值,在:

class CustomerHeaderRecord:
    def __init__( self, rec, debug = False ):
        self.record = rec
        self.acct   = rec[ 84:104 ]

acct 变量的内容正确显示在屏幕上。

以下是写入数据库的代码(acct 值作为val_1 变量传入):

class MQ:
    def __init__( self, rec, debug = False ):
        self.customer_record = CustomerHeaderRecord( rec, debug )
        self.add_record(self.customer_record.acct, self.cm_custid)

    def add_record(self, val_1, val_2):
        cur = conn.cursor()
        qry = "select count(*) from table_name where value1 = :val1"
        cur.execute(qry, {'val1':val_1})
        count = cur.fetchone()
        if count[0] == 0:
            cur = conn.cursor()
            qry = "insert into table_name (value1, value2) values(:val1, :val2)"
            cur.execute(qry, {'val1':val_1, 'val2':val_2})
            conn.commit()

acct 值无法正确进入数据库。我用谷歌搜索了一堆关于 unicode 和 UTF-8 的东西,但还没有找到任何对我有帮助的东西。在数据库中,NLS_LANGUAGE 是“American”,NLS_CHARACTERSET 是“AL32UTF8”。

在插入之前/期间我是否需要对acct 变量“做某事”?

【问题讨论】:

  • print repr(acct) 的输出是什么?您的数据很可能已经编码,但不是 Oracle 使用的 UTF-8 编码。
  • @MartijnPieters - 它显示为'PF R\xe9solu Canada Inc'。刚打印时没有repr,它是PF Résolu Canada Inc
  • 这是拉丁语 1;我会给你写一个答案。

标签: python oracle


【解决方案1】:

您的输入文件似乎以 Latin-1 编码。将此解码为unicode 数据; cx_Oracle 将为您完成剩下的工作:

acct    = rec[ 84:104 ].decode('latin1')

或使用codecs.open() function打开文件进行自动解码:

inputfile = codecs.open(filename, 'r', encoding='latin1')

inputfile 读取数据将为您提供unicode 数据。

在插入时,cx_Oracle 库会将 unicode 值编码为 Oracle 期望的正确编码。您确实需要在连接之前将NLS_LANG 环境变量设置为AL32UTF8,无论是在shell 中还是在Python 中:

os.environ["NLS_LANG"] = ".AL32UTF8"

您可能需要查看Python Unicode HOWTO 了解更多详情。

【讨论】:

  • 使用 rec[ 84:104 ].decode('latin1') 导致 UnicodeEncodeError' of 'ascii' 编解码器无法对位置 259 中的字符 u'\xe9' 进行编码:序数不在范围内 (128)'。与codecs.open 类似的结果。
  • 不,rec[ 84:104 ].decode('latin1') 本身并没有导致该错误;请注意,这是一个 encode 错误,而该语句正在执行解码。您要么将结果打印到日志文件,要么打印到哑终端; python 正在自动将unicode 值转换回ASCII,因为这是它可以尝试将unicode 值和字节码组合或将其打印到输出文件的唯一方法。
  • 在到目前为止显示的代码的上下文中,这应该可以工作。如果没有,您能否向我们展示完整回溯(编辑您的问题)。
  • 是的,我确实在打印该值,这就是引发错误的地方。我已删除打印,现在尝试在查询中使用 acct 值时出现不同的错误。我将编辑问题。
  • 如果我按照建议添加.decode('latin1'),当它到达执行选择语句的行时,我会得到一个TypeError - not enough arguments for format string;即,我尝试使用该 acct/val_1 值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 2013-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 2011-04-03
相关资源
最近更新 更多