UnicodeDecodeError: 'ascii'编解码器无法解码字节,位置为:序数不在128的范围内

5
我对这个错误做了一些研究,但实际上并不清楚发生了什么。据我所知,我遇到的问题基本上是因为我正在从一种编码类型转换为另一种编码类型。
def write_table_to_file(table, connection):
    db_table = io.StringIO()
    cur = connection.cursor()
    #pdb.set_trace()
    cur.copy_to(db_table, table)
    cur.close()
    return db_tabl

这个方法让我头疼。运行这个方法时,会输出以下错误信息:

[u350932@config5290vm0 python3]$ python3 datamain.py 
Traceback (most recent call last):
  File "datamain.py", line 48, in <module>
    sys.exit(main())
  File "datamain.py", line 40, in main
    t = write_table_to_file("cms_jobdef", con_tctmsv64)
  File "datamain.py", line 19, in write_table_to_file
    cur.copy_to(db_table, table)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa0 in position 40: ordinal not in range(128)

我会翻译中文,这段内容是关于编程的。它指的是从数据库检索表时客户端的编码方式。
tctmsv64=> SHOW CLIENT_ENCODING;
 client_encoding
-----------------
 sql_ascii
(1 row)

数据库编码是LATIN1

我要将它们放入的数据库编码为

S104838=# SHOW CLIENT_ENCODING;
 client_encoding
-----------------
 WIN1252
(1 row)

数据库编码为UTF8

从我找到的线程中,建议更改编码

To correct your function, you'll have to know what encoding the byte
string is in, and convert it to unicode using the decode() method,
and compare that result to the unicode string.

http://www.thecodingforums.com/threads/unicodedecodeerror-ascii-codec-cant-decode-byte-0xa0-in-position-10-ordinal-not-in-range-128.336691/

问题在于当我尝试使用解码方法时,会出现文件类型不正确的错误。我查看了Python 3.4中关于类io.StringIO(initial_value='', newline='\n')¶方法的文档,但没有找到更改编码的内容。
我还发现了这个页面,它概述了这个问题,但我无法弄清楚需要做什么来解决它。

https://wiki.python.org/moin/UnicodeDecodeError

基本上,我很困惑发生了什么事情,也不确定该如何解决。非常感谢任何帮助。祝好。

SQL_ASCII 更像是一个未编码标识。它告诉数据库将接收的字节存储,不进行转换或验证。它不应该被使用。您可能在源数据库中有不同编码的文本混合。 - Craig Ringer
2个回答

3
Python 3在文本编码方面改变了文件I/O的行为 - 我认为这是很大的进步。你可以查看Python 3文本文件处理来获取更多信息。
看起来像是psycopg2发现你传递了一个原始的文件对象,然后尝试将它所处理的字符串编码为字节序列以便写入文件。由于你没有指定其他东西,因此该库假设你想要使用ascii编码进行文件操作。
我建议使用io.BytesIO对象代替StringIO,并在将数据从源数据库中复制到新数据库时明确指定源编码。
尽管如此,我还是会感到惊讶,如果你的SQL_ASCII源数据库出现无效、混合或其他损坏的文本数据而出现问题。

1

首先感谢Craig的回应,它对我有很大帮助,让我意识到需要找到一个好的方法来完成这个任务,否则我的新数据库中的数据可能会损坏。这不是我们想要的!经过更多的搜索,我发现这个链接非常有用。

https://docs.python.org/3/howto/unicode.html

我最终使用了StreamRecorder模块,它工作得非常好。以下是我的可工作代码片段:
def write_table_to_file(table, connection):
    db_table = io.BytesIO()
    cur = connection.cursor()
    cur.copy_to(codecs.StreamRecoder(db_table,codecs.getencoder('utf-8'), codecs.getdecoder('latin-1'),
                                     codecs.getreader('utf-8'), codecs.getwriter('utf-8')), table)
    cur.close()
    return db_table

长话短说,我在运行时从latin-1转换为utf-8,并且一切正常,我的数据看起来不错。再次感谢Craig的反馈 :)

1
反馈你的进展是很好的,但如果将来你是提问者,并且你自己没有提供最终答案,最好将这种信息放在问题中,使其明显(例如使用__UPDATE:__),表明你正在补充原始问题。 - Rob Grant

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