UnicodeDecodeError:'ascii'编解码器无法解码位置中的字节:序号不在范围内(128)

时间:2014-06-25 05:06:28

标签: postgresql encoding utf-8 latin1 python-3.4

我已经对这个错误进行了一些研究,并且无法真正了解正在发生的事情。据我所知,我基本上遇到了问题,因为我正在从一种编码转换为另一种编码。

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/

问题是,当我尝试使用解码方法时,我得到的抱怨是它不是文件类型。我已经看过类io.StringIO的python 3.4方法(initial_value ='',newline ='\ n')¶方法,但在更改编码时找不到任何内容。

我还发现这个页面概述了问题,但我无法弄清楚我需要做些什么来解决它

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

基本上我对发生了什么感到困惑,不知道如何解决它。任何帮助将不胜感激。

干杯

2 个答案:

答案 0 :(得分:1)

Python 3改变了文本编码周围的文件I / O行为 - 大大改善了IMO。您可能会发现Processing Text Files in Python 3信息丰富。

看起来psycopg2看到你传递了一个原始文件对象并试图将它正在处理的字符串编码为字节序列以便写入文件,并假设(因为你没有指定任何东西) else)你想对文件使用ascii编码。

我使用io.BytesIO对象而不是StringIO,并在新数据库中执行copy_from时指定源编码。

如果由于SQL_ASCII源数据库中的无效,混合或其他borked文本没有问题,我会感到惊讶。

答案 1 :(得分:1)

首先感谢克雷格的回复。这让我意识到我需要找到一个很好的方法,否则新数据库中的数据将会损坏,这非常有帮助。不是我们想要的!经过一番谷歌搜索后,这个链接非常有用

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的反馈:)