我正在使用SQLAlchemy和MySQL,以及files
表来存储文件。该表的定义如下:
mysql> show full columns in files;
+---------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+---------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
| id | varchar(32) | utf8_general_ci | NO | PRI | NULL | | select,insert,update,references | |
| created | datetime | NULL | YES | | NULL | | select,insert,update,references | |
| updated | datetime | NULL | YES | | NULL | | select,insert,update,references | |
| content | mediumblob | NULL | YES | | NULL | | select,insert,update,references | |
| name | varchar(500) | utf8_general_ci | YES | | NULL | | select,insert,update,references | |
+---------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+
类型
MEDIUMBLOB
的content列是文件的存储位置。在SQLAlchemy中,该列声明为:__maxsize__ = 12582912 # 12MiB
content = Column(LargeBinary(length=__maxsize__))
我不太确定SQLAlchemy的
BINARY
类型和 LargeBinary
类型之间的区别。或者是MySQL的 VARBINARY
类型和 BLOB
类型之间的区别。我不确定这是否重要。问题:每当我在该表中存储实际的二进制文件(即Python
bytes
或b''
对象)时,我都会收到以下警告.../python3.4/site-packages/sqlalchemy/engine/default.py:451: Warning: Invalid utf8 character string: 'BCB121'
cursor.execute(statement, parameters)
我不想只是忽略警告,但似乎文件完好无损。如何优雅地处理此警告,如何解决其原因?
旁注: This question似乎相关,并且它似乎是一个MySQL错误,它试图将所有传入的数据转换为UTF-8(this answer)。
最佳答案
原来,这是一个驱动程序问题。显然,默认的MySQL驱动程序在Py3和utf8支持下迷失了方向。将cymysql安装到虚拟Python环境中可以解决此问题,并且警告会消失。
修复:找出MySQL是否通过套接字或端口连接(请参阅here),然后相应地修改连接字符串。就我而言,使用套接字连接:
mysql+cymysql://user:pwd@localhost/database?unix_socket=/var/run/mysqld/mysqld.sock
否则,请使用
port
参数。编辑:上面的代码解决了编码问题,但又引起了另一个问题:blob大小。由于a bug in CyMySQL,大于8M的Blob无法提交。切换到PyMySQL可以解决该问题,尽管它似乎具有大 Blob 的similar issue。