Pandas to_sql出现Unicode解码错误

17
我有一个pandas数据帧,是通过read_csv加载的。我试图通过to_sql将其推送到数据库,但当我尝试这样做时,出现了问题。
df.to_sql("assessmentinfo_pivot", util.ENGINE)

我会遇到一个 UnicodeDecodeError 错误:

UnicodeEncodeError: 'ascii' codec can't encode characters in position 83-84: ordinal not in range(128)

to_sql没有编码选项来指定utf-8,而Engine是使用utf-8编码创建的。

ENGINE = create_engine("mssql+pymssql://" +
                       config.get_local('CEDS_USERNAME') + ':' +
                       config.get_local('CEDS_PASSWORD') + '@' +
                       config.get_local('CEDS_SERVER') + '/' +
                       config.get_local('CEDS_DATABASE'),
                       encoding="utf-8")

任何关于如何正确运行此代码的pandas见解?大部分搜索结果都是人们在使用to_csv时遇到类似错误,只需添加encoding="utf-8"即可解决,但这里不幸不是一个选项。我试图将文件缩小,但即使只剩下标题,它仍然会出现错误:http://pastebin.com/F362xGyP

你能提供一个可重现的例子吗?(一些示例数据和能够复现错误的代码) - joris
错误仅出现在我上面放在pastebin中的标题中。由于对源表进行了一些透视,列具有一些较长的名称。 - lathomas64
在尝试创建透视表时,一些来自西班牙数据源名称的特殊字符(如ó)会出现在这里。我希望能够在to_sql调用中处理这个问题,而不是必须从标题中删除这些字符。 - lathomas64
这些标题被用作数据库的列名。即使数据库软件允许在列名中使用特殊字符,我也会小心地只使用ASCII子集,以确保未引用的标识符安全。从标题来看,这不应该进入一个数据库表格,至少如果你遵循通常的规范化指南。这些标题包含着数据。 - BlackJack
3个回答

20

我在使用pymysql和pandas.to_sql的组合时遇到了完全相同的问题。

更新,以下是我成功解决该问题的方法:

不要将字符集作为参数传递,而是直接将其附加到连接字符串中:

connect_string = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(DB_USER, DB_PASS, DB_HOST, DB_PORT, DATABASE)

该问题似乎发生在pymysql中,错误的原因似乎是您定义的编码未能正确地转发和设置为pymsql连接设置时所需的编码。

为了调试,我在pymysql _do_execute_many函数中强制指定了

encoding = 'utf-8'

这让我明白了问题的原因。


6
我在Python 3.7中遇到了类似的问题: UnicodeEncodeError:“charmap”编解码器无法在位置0处编码字符'\ufffd':该字符映射到
问题出在我定义引擎的方式上。我将字符集定义为utf-8,但它没有被识别:
# Connecting to the database(reference for checkout_listener not added)
def MysqlConnection(DbName):
    DB_TYPE = 'mysql'
    DB_DRIVER = 'mysqldb'
    DB_NAME = DbName
    POOL_SIZE = 100
    CHARSET = 'utf-8'

    SQLALCHEMY_DATABASE_URI = '%s+%s://%s:%s@%s:%s/%s?%s' % (DB_TYPE, DB_DRIVER, DB_USER,
                                                             DB_PASS, DB_HOST, DB_PORT, DB_NAME, CHARSET)
    ENGINE1 = create_engine(
        SQLALCHEMY_DATABASE_URI, pool_size=POOL_SIZE, pool_recycle=3600, echo=False)
    event.listen(ENGINE1, 'checkout', checkout_listener)
    return (ENGINE1);

这在Python 2上运行良好,但在Python 3上会出现charmap错误。我找到的唯一解决方案是以不同的方式编写engine,并将字符集添加到定义字符串中:

connection_string = f"{mysql_user}:{mysql_password}@localhost:3306/{db_name}?charset=utf8"
engine = create_engine(f'mysql://{connection_string}')

2

我已经解决了MySQL数据库中字符集的问题(UTF-8),并将以下内容添加到pymysql连接中:charset='utf8'


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