Cra*_*ght 6 python mysql sqlalchemy
使用sqlalchemy 0.9.7,我试图在启用utf8mb4的情况下将表情符号存储到MySQL 5.5中.然而,由于某种原因,sqlalchemy正在杀死我的表情符号字符,我无法弄清楚为什么.在尝试通过sqlalchemy保存数据之前,我可以在对象中看到表情符号字符.保存后,抛出错误,表情符号呈现为????.
错误如下.请注意,它被输出type(post.message)和调试消息所包围post.message.
--------------------------------------------------------------------------------
DEBUG in __init__ [/mnt/hgfs/crw/dev/hyper/hyper/blueprint/chat/__init__.py:274]:
<type 'unicode'>
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
DEBUG in __init__ [/mnt/hgfs/crw/dev/hyper/hyper/blueprint/chat/__init__.py:275]:
--------------------------------------------------------------------------------
/mnt/hgfs/crw/dev/hyper/env/local/lib/python2.7/site-packages/sqlalchemy/engine/default.py:436: Warning: Incorrect string value: '\xF0\x9F\x98\x83' for column 'message' at row 1
  cursor.execute(statement, parameters)
--------------------------------------------------------------------------------
DEBUG in __init__ [/mnt/hgfs/crw/dev/hyper/hyper/blueprint/chat/__init__.py:277]:
<type 'unicode'>
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
DEBUG in __init__ [/mnt/hgfs/crw/dev/hyper/hyper/blueprint/chat/__init__.py:278]:
????
--------------------------------------------------------------------------------
我的代码看起来像:
Base = declarative_base()
post = Table('post', Base.metadata,
        Column("id", Integer, primary_key=True),
        Column("message", UnicodeText),
        Column("created_at", DateTime),
        Column("updated_at", DateTime),
    )
mapper(Post, post)
我需要做任何其他设置才能使其工作吗?
更新:如果我执行以下操作:
Base = declarative_base()
post = Table('post', Base.metadata,
        Column("id", Integer, primary_key=True),
        Column("message", UnicodeText),
        Column("created_at", DateTime),
        Column("updated_at", DateTime),
        mysql_engine='InnoDB',
        mysql_charset='utf8mb4'
    )
mapper(Post, post)
我得到以下内容:
--------------------------------------------------------------------------------
DEBUG in __init__ [/mnt/hgfs/crw/dev/hyper/hyper/blueprint/chat/__init__.py:274]:
<type 'unicode'>
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
DEBUG in __init__ [/mnt/hgfs/crw/dev/hyper/hyper/blueprint/chat/__init__.py:275]:
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
DEBUG in __init__ [/mnt/hgfs/crw/dev/hyper/hyper/blueprint/chat/__init__.py:277]:
<type 'unicode'>
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
DEBUG in __init__ [/mnt/hgfs/crw/dev/hyper/hyper/blueprint/chat/__init__.py:278]:
????
--------------------------------------------------------------------------------
没有错误,但它仍然消灭了表情符号.到底是怎么回事?!
更新2:
更改要调用的数据库URI:
mysql+mysqldb://user:pass@localhost/datab?charset=utf8
至
mysql+mysqldb://user:pass@localhost/datab
解决了这个问题.sqlalchemy在我尝试使用时抛出了一个错误charset=utf8mb4&use_unicode=0.但那是明智的吗?根据http://docs.sqlalchemy.org/en/rel_0_9/dialects/mysql.html#module-sqlalchemy.dialects.mysql.mysqldb,它不是!非常喜欢这个解决方案的任何反馈.
下面是我如何让表情符号等工作。我正在使用 Python 3.5/Flask/Flask-SQLAlchemy。
注意:此修复假设您在开发中的时间足够早,可以通过运行db.drop_all()和重新创建数据库db.create_all()。
按照本指南中的建议,打开一个数据库控制台并运行ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
按照此答案中的建议,添加?charset=utf8mb4到SQLALCHEMY_DATABASE_URI字符串的末尾。
mysql+mysqlconnector://{username}:{password}@{hostname}/{databasename}mysql+mysqlconnector://{username}:{password}@{hostname}/{databasename}?charset=utf8mb4现在只需重新运行db.drop_all()和db.create_all()。
这是对我有用的解决方案。set_unicode连接第一次进入连接池时被调用,并且只被调用一次。SET NAMES基本上修复了从代码到数据库存储的整个管道,以确保使用正确的 UTF-8 字符集 ( utf8mb4)。只要utf8mb4确保端到端,表情符号就应该被很好地存储/呈现,因为它们只是 BMP(基本多语言平面)之外的常规 unicode 字符,不幸的是 MySQL 决定只实现 3 字节 Unicode 实现是一个好主意为 BMP 作为unicode字符集。
请参阅SQLAlchemy 事件参考以了解其他相关事件挂钩,您可以利用这些挂钩通过连接配置调整进行连接。
import logging
from sqlalchemy import event
logger = logging.getLogger(__name__)     
@event.listens_for(Pool, "connect")
def set_unicode(dbapi_conn, conn_record):
    cursor = dbapi_conn.cursor()
    try:
        cursor.execute("SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'")
    except Exception as e:
        logger.debug(e)
更新:关于连接字符串中的额外选项,我更喜欢明确并指定,charset=utf8mb4因为我的环境的默认字符集是utf8(这是为什么表情符号无法正确编码的罪魁祸首),但use_unicode=0除非您在 python 2.x 和性能上运行,否则永远不要指定正如您在链接中指出的那样,这是一个瓶颈。
| 归档时间: | 
 | 
| 查看次数: | 2898 次 | 
| 最近记录: |