to_sql报JSON错误实为误传DataFrame给json.dumps();真正问题常是连接失败、表不存在或列名含非法字符;提速需设chunksize和method='multi';中文乱码须三处utf8mb4一致;datetime问题源于时区不匹配或类型不兼容。

to_sql 写不进 MySQL,报 TypeError: Object of type DataFrame is not JSON serializable?
这不是 to_sql 的错,是误把整个 DataFrame 当作参数传给了 json.dumps() 类函数(比如用了 logging.info(df) 或自定义装饰器)。to_sql 本身不涉及 JSON 序列化。
真正卡住的常见原因是连接没建好或表结构不匹配。检查三件事:
-
sqlalchemy.create_engine()的 URL 是否包含正确用户名、密码、数据库名,且 MySQL 服务正在运行 - 目标表是否存在?如果
if_exists='fail'(默认),表存在就直接报错,不是 JSON 错 - 列名是否含空格、中文或特殊符号?MySQL 默认不支持,会触发底层 SQL 构造失败,错误信息可能被吞掉,表现像“莫名报错”
to_sql 插入速度慢,10 万行要几分钟?
默认是逐行 INSERT,网络往返多、事务开销大。提速关键在两个参数:
- 加
chunksize=1000:分批提交,减少单次 SQL 长度和事务压力 - 设
method='multi':用INSERT INTO ... VALUES (),(),()批量语法,比单条快 5–10 倍 - 避免
index=True写入索引列,除非真需要;若写入已有主键表,确保df索引与主键类型一致(比如int64对 MySQLBIGINT),否则隐式转换拖慢插入
示例:df.to_sql('my_table', engine, if_exists='append', chunksize=1000, method='multi')
立即学习“Python免费学习笔记(深入)”;
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
中文乱码、emoji 存成问号或报 Incorrect string value
根本原因不是 Pandas,是 MySQL 连接层和表字符集没对齐。三个地方必须都是 utf8mb4:
- 创建引擎时 URL 加参数:
?charset=utf8mb4,例如mysql+pymysql://u:p@h:3306/db?charset=utf8mb4 - 目标表的字符集:用
SHOW CREATE TABLE my_table确认DEFAULT CHARSET=utf8mb4,不是utf8 - MySQL 服务端配置:确认
my.cnf中collation-server = utf8mb4_unicode_ci和character-set-server = utf8mb4
漏掉任意一个,to_sql 都会静默截断或报错。
datetime 列写入后变成 0000-00-00 或时区错乱
Pandas 的 datetime64[ns] 在写入 MySQL 时,会按本地时区转为 naive datetime,再由 SQLAlchemy 映射为 DATETIME。问题常出在:
- MySQL 服务器时区 ≠ Python 进程时区(如服务器是 UTC,Python 是 CST),导致时间偏移 8 小时
-
df['time']含 NaT 或非法日期(如2023-02-30),to_sql默认静默转为NULL或 0 值,不会报错 - 目标列为
DATE类型却传了带时间的datetime,MySQL 截断时间部分,只留日期
稳妥做法:写入前用 df['time'] = pd.to_datetime(df['time'], errors='coerce') 清洗,再确认目标列类型是否匹配(DATETIME 接收完整时间,DATE 只收日期)。
时区敏感场景建议显式转为 UTC:df['time'] = df['time'].dt.tz_localize('Asia/Shanghai').dt.tz_convert('UTC'),再写入。

















