pandas.read_sql连接对象必须是SQLAlchemy Engine;直接传sqlite3或pymysql的Connection会报错,因pandas要求底层支持execute方法。
用
读取数据库时,连接对象必须是 SQLAlchemy Engine
直接传
或 pymysql 的
会报错:
。pandas 要求底层是
。
正确做法是用
构建连接:
立即学习
“
Python免费学习笔记(深入)
”;
SQLite 路径支持相对路径,但注意当前工作目录可能不是脚本所在目录
MySQL/PostgreSQL 需要安装对应驱动(
、
),否则
会抛
如果 SQL 语句含参数,别用 Python 字符串格式化,改用
默认不写表头和索引,但生产环境通常需要显式控制
直接调
会把 DataFrame 的行索引(index)也写进去,且列名作为第一行——这常被误认为“多了一列”或“首行错位”。
常见组合:
Python 3.14.3
微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。
下载
是最常用选项,尤其导出给 Excel 或其他系统消费时
中文列名或数据导出乱码?加
(Windows Excel 友好),不要用
数值列含 NaN,默认转为空字符串;若需统一为
或
,先用
大数据量导出 CSV 容易内存爆掉,得流式处理
当表有百万行以上,
一次性加载全量到内存,再
,很可能触发
或拖慢整个流程。
替代方案:用
分批读 + 追加写入:
值不是越大越好,5k–50k 之间较稳妥,取决于单行平均大小和可用内存
首次写入需
,后续必须
,否则 CSV 每块都带列名
不能用
直接追加,因为
会重写整个文件头逻辑
导出后 CSV 列顺序/类型和数据库不一致?问题出在 SQL 查询本身
pandas 不会自动按数据库字段定义顺序或类型映射 CSV。比如某列在 DB 是
,读出来是
,但
默认转成字符串(ISO 格式),且毫秒部分可能被截断。
确保 SELECT 明确写出字段名,避免
导致顺序不可控
时间列要保留精度?用
参数或导出前
整数列含 NULL,pandas 会转成
(因 NaN 是浮点),导出后带
。解决:先
(注意是大写 I)再导出
真正卡住的往往不是语法,而是对 SQL 结果结构、pandas 类型推断、CSV 文本本质这三层之间隐式转换的误判。
pandas.read_sqlsqlite3.connect(...)ConnectionAttributeError: 'Connection' object has no attribute 'execute'sqlalchemy.engine.Enginesqlalchemy.create_enginefrom sqlalchemy import create_engine
import pandas as pd
engine = create_engine("sqlite:///example.db")
或 MySQL:engine = create_engine("mysql+pymysql://user:pass@localhost/dbname")
df = pd.read_sql("SELECT * FROM users", engine)
pymysqlpsycopg2create_engineModuleNotFoundErrorpd.read_sql("SELECT * FROM t WHERE id = :id", engine, params={"id": 123})to_csvdf.to_csv("out.csv")df.to_csv("out.csv", index=False, header=True) # 推荐:无索引,有列名
df.to_csv("out.csv", index=False, header=False) # 纯数据,无列名(适合后续程序解析)
df.to_csv("out.csv", index=True, header=True) # 保留索引(如需溯源 row_id)index=Falseencoding="utf-8-sig"utf-8NULL0df.fillna(...)pd.read_sqlto_csvMemoryErrorchunksizewith open("large_out.csv", "w", encoding="utf-8-sig") as f:
first_chunk = True
for chunk in pd.read_sql("SELECT * FROM logs", engine, chunksize=50000):
chunk.to_csv(f, header=first_chunk, index=False, mode="a")
first_chunk = Falsechunksizeheader=Trueheader=Falsedf.to_csv(..., mode="a")to_csvDATEdatetime64[ns]to_csv*parse_dateschunk["created_at"].dt.strftime("%Y-%m-%d %H:%M:%S.%f")float64.0astype("Int64")