python - Unicode解码错误: 'ascii' codec can't decode byte 0x92 in position 47: ordinal not in range(128)

标签 python postgresql python-2.7 encoding utf

我正在尝试使用 Python 在 StringIO 对象中写入数据,然后使用 psycopg2 的 copy_from() 函数最终将这些数据加载到 postgres 数据库中。

首先,当我这样做时,copy_from() 抛出错误:错误:编码“UTF8”的字节序列无效:0xc92 所以我遵循了 this question .

我发现我的 Postgres 数据库有 UTF8 编码。

我正在写入数据的文件/StringIO 对象显示其编码如下: setgid 非 ISO 扩展 ASCII 英文文本,行很长,带有 CRLF 行终止符

我尝试将写入中间文件/StringIO 对象的每个字符串编码为 UTF8 格式。为此,对每个字符串使用 .encode(encoding='UTF-8',errors='strict'))。

这是我现在得到的错误: UnicodeDecodeError: 'ascii' 编解码器无法解码位置 47 中的字节 0x92:序号不在范围内 (128)

这是什么意思?我该如何解决?

编辑: 我正在使用 Python 2.7 我的一些代码:

我从一个 MySQL 数据库中读取,该数据库的数据按照 MySQL Workbench 以 UTF-8 编码。 这是将我的数据(从 MySQL 数据库获得)写入 StringIO 对象的几行代码:

# Populate the table_data variable with rows delimited by \n and columns delimited by \t
row_num=0
for row in cursor.fetchall() :

    # Separate rows in a table by new line delimiter
    if(row_num!=0):
        table_data.write("\n")

    col_num=0
    for cell in row:    
        # Separate cells in a row by tab delimiter
        if(col_num!=0):
            table_data.write("\t") 

        table_data.write(cell.encode(encoding='UTF-8',errors='strict'))
        col_num = col_num+1

    row_num = row_num+1   

这是从我的 StringIO 对象 table_data 写入 Postgres 数据库的代码:

cursor = db_connection.cursor()
cursor.copy_from(table_data, <postgres_table_name>)

最佳答案

问题是您在 str 对象上调用 encode

str 是一个字节串,通常表示以某种方式编码的文本,例如 UTF-8。当您对其调用 encode 时,它首先必须被解码回文本,因此文本可以重新编码。默认情况下,Python 通过调用 s.decode(sys.getgetdefaultencoding()) 来实现,而 getdefaultencoding() 通常返回 'ascii'

所以,您说的是 UTF-8 编码的文本,将其解码为 ASCII,然后将其重新编码为 UTF-8。

一般的解决方案是用正确的编码显式调用decode,而不是让Python使用默认值,然后对结果进行encode

但是当正确的编码已经是你想要的编码时,更简单的解决方案是跳过 .decode('utf-8').encode('utf-8') 并且只是使用 UTF-8 str 作为它已经存在的 UTF-8 str

或者,如果您的 MySQL 包装器具有允许您指定编码并返回 CHAR/VARCHARunicode 值的功能/TEXT 列而不是 str 值(例如,在 MySQLdb 中,您将 use_unicode=True 传递给 connect 调用,或者 charset='UTF-8' 如果您的数据库太旧而无法自动检测),就这样做吧。然后您将拥有 unicode 对象,您可以对它们调用 .encode('utf-8')

一般来说,处理 Unicode 问题的最好方法是最后一个——尽早解码所有内容,用 Unicode 进行所有处理,然后尽可能晚地编码。但无论哪种方式,你都必须保持一致。不要在可能是 unicode 的东西上调用 str;不要将 str 文字连接到 unicode 或将其传递给 replace 方法;等等。任何时候你混合搭配,Python 都会使用你的默认编码为你隐式转换,这几乎不是你想要的。

附带说明一下,这是 Python 3.x 的 Unicode 更改有助于解决的众多问题之一。首先,str 现在是 Unicode 文本,而不是编码字节。更重要的是,如果你编码字节,例如,在bytes对象中,调用encode会给你一个AttributeError 而不是试图静默解码,以便它可以重新编码。而且,类似地,尝试混合和匹配 Unicode 和字节会给你一个明显的 TypeError,而不是在某些情况下成功的隐式转换,并给出关于你没有进行的编码或解码的神秘消息求于他人。

关于python - Unicode解码错误: 'ascii' codec can't decode byte 0x92 in position 47: ordinal not in range(128),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26619801/

相关文章:

python - python 有没有办法判断变量是否是系统命令

python - 跟踪变量 - ComboBox Tkinter

ruby-on-rails - 使用 pg_search gem 在 Heroku 上进行全文搜索

postgresql - Solr 可以用作缓存的替代品吗?

python - 无法使用 python selenium 获取动态元素

python - 如何修复 PySide2 QPixmapCache.find() DeprecationWarning?

ruby-on-rails - 带有 json 列参数的范围

node.js - Node gyp:gyp 错误!无法加载共享libpython2.7.so.1.0

python - 获取文本小部件的长度

python - 迭代 wxPython 中的控件以保存 session 数据