如何在 SQLAlchemy 的`create_engine` 中使用`charset` 和`encoding`(创建pandas 数据框)?
Posted
技术标签:
【中文标题】如何在 SQLAlchemy 的`create_engine` 中使用`charset` 和`encoding`(创建pandas 数据框)?【英文标题】:how to use `charset` and `encoding` in `create_engine` of SQLAlchemy (to create pandas dataframe)? 【发布时间】:2017-12-29 23:55:09 【问题描述】:我对 SQLAlchemy 中 charset 和 encoding 的工作方式感到非常困惑。我了解(并已阅读)charsets and encodings 之间的区别,并且我对the history of encodings 有很好的了解。
我在 latin1_swedish_ci 中的 mysql 中有一个表(为什么?可能因为this)。我需要创建一个 pandas 数据框,在其中我得到正确的字符(而不是奇怪的符号)。最初,这是在代码中:
connect_engine = create_engine('mysql://user:password@1.1.1.1/db')
sql_query = "select * from table1"
df = pandas.read_sql(sql_query, connect_engine)
我们开始遇到Š
字符的问题(对应于u'\u0160'
unicode,但我们得到的是'\x8a')。我希望这会起作用:
connect_engine = create_engine('mysql://user:password@1.1.1.1/db', encoding='utf8')
但是,我继续得到'\x8a'
,我意识到这是有道理的,因为编码参数的默认值是utf8
。所以,然后,我尝试encoding='latin1'
来解决这个问题:
connect_engine = create_engine('mysql://user:password@1.1.1.1/db', encoding='latin1')
但是,我仍然得到相同的 '\x8a'。需要明确的是,在这两种情况下(encoding='utf8'
和 encoding='latin1'
),我可以使用mystring.decode('latin1')
,但不能使用mystring.decode('utf8')
。
然后,我重新发现了连接字符串中的charset
参数,即'mysql://user:password@1.1.1.1/db?charset=latin1'
。在尝试了所有可能的字符集和编码组合之后,我发现这个可行:
connect_engine = create_engine('mysql://user:password@1.1.1.1/db?charset=utf8')
如果有人能解释我如何正确使用连接字符串中的charset
,以及create_engine
中的encoding
参数,我将不胜感激?
【问题讨论】:
【参考方案1】:encoding
参数不能正常工作。
因此,正如@doru 在this link 中所说,您应该在连接字符串的末尾添加?charset=utf8mb4
。像这样:
connect_string = 'mysql+pymysql://:@:/?charset=utf8mb4'.format(DB_USER, DB_PASS, DB_HOST, DB_PORT, DATABASE)
【讨论】:
这以一种意想不到的方式救了我。是否存在其他已知问题,驱动程序/DBAPI 选择 latin1 并忽略服务器端设置?我在服务器上有这个设置,不知道为什么我也需要在连接器上设置它来修复问题。【参考方案2】:encoding
是用于编码/解码的编解码器在 SQLAlchemy 中。来自文档:
对于那些检测到 DBAPI 不支持 Python
unicode
对象,这个编码是用来判断 源/目标编码。它不用于 DBAPI 直接处理 unicode。[...]
要正确配置系统以容纳 Python
unicode
对象, DBAPI 应配置为最大程度地处理 unicode 适当的程度[...]
mysql-python 直接处理 unicode,所以不需要使用这个设置。
charset
是特定于 mysql-python 驱动程序的设置。来自the documentation:
此字符集是连接的客户端字符集。
此设置控制服务器上的three variables,特别是character_set_results
,这是您感兴趣的。设置后,字符串将作为unicode
对象返回。
请注意,这仅适用于数据库中有 latin1 编码数据的情况。如果您已将 utf-8 字节存储为 latin1,则改用 encoding
可能会更好。
【讨论】:
感谢@univerio,我还是有点迷茫,因为有几个名字,我不打算放置它们:database -> python driver -> mysql-python interface (DBAPI?) -> SQLALchemy。驱动和接口、DBAPI一样吗? @toto_tico 驱动和 DBAPI 是一回事。 (从技术上讲,DBAPI 是 PEP 249 定义的接口,驱动程序是实现此接口的库,但没必要这么迂腐。)所以它是 database -> driver/DBAPI -> SQLAlchemy i>.【参考方案3】:我遇到了同样的问题。我刚刚在网址末尾添加了 ?charset=utf8mb4。
这是我的:
之前
SQL_ENGINE = sqlalchemy.create_engine('mysql+pymysql://'+MySQL.USER+':'+MySQL.PASSWORD+'@'+MySQL.HOST+':'+str(MySQL.PORT)+'/'+MySQL.DB_NAME)
之后
SQL_ENGINE = sqlalchemy.create_engine('mysql+pymysql://'+MySQL.USER+':'+MySQL.PASSWORD+'@'+MySQL.HOST+':'+str(MySQL.PORT)+'/'+MySQL.DB_NAME + "?charset=utf8mb4")
【讨论】:
【参考方案4】:这对我有用。
from sqlalchemy import create_engine
from sqlalchemy.engine.url import URL
db_url =
'database': "dbname",
'drivername': 'mysql',
'username': 'myname',
'password': 'mypassword',
'host': '127.0.0.1',
'query': 'charset': 'utf8', # the key-point setting
engine = create_engine(URL(**db_url), encoding="utf8")
【讨论】:
以上是关于如何在 SQLAlchemy 的`create_engine` 中使用`charset` 和`encoding`(创建pandas 数据框)?的主要内容,如果未能解决你的问题,请参考以下文章