Python连接MySQL数据库:pymysql安装与查询教程
在编写自动化脚本、后端接口或数据处理程序时,从关系型数据库中调取业务数据是一项最基本的操作。假设你正准备开发一个轻量的数据报表程序,需要从现有的 MySQL 数据库中读取指定用户的订单信息;或者刚刚部署好本地的 MySQL 数据库,希望通过 Python 代码快速验证数据连通性。面对这些场景,PyMySQL 是 Python 生态中最常用且直接的解决方案之一。
本文将围绕 Python 连接 MySQL 数据库 这一核心任务,系统讲解通过 pymysql 库完成从环境准备、驱动安装、连接配置到编写查询、安全防注入及异常处理的完整落地流程,帮助你掌握规范、稳定的数据库查询方法。
一、PyMySQL 运行原理与核心架构
在开始编码前,先了解底层通信机制有助于快速定位后续可能遇到的网络与权限问题。PyMySQL 是一个使用纯 Python 语言实现的 MySQL 客户端驱动库,完全兼容 Python 数据库 API 规范(PEP 249)。
与早期依赖 C 语言底层编译的 MySQLdb 库不同,PyMySQL 无须在操作系统上提前配置 C 语言编译器和 MySQL 客户端开发头文件(如 mysql_config),直接利用 Python 原生网络套接字(Socket)封装并实现 MySQL 客户端/服务端握手协议。这使得它在 Windows、macOS 以及精简版 Linux Docker 容器中均可开箱即用。
二、环境准备与 PyMySQL 安装
在执行代码之前,需要准备好以下两项基础条件:
- 运行中的 MySQL 服务:可以是本机运行的 MySQL、局域网服务器或云端 RDS 实例。记录好主机地址(Host)、端口(Port,默认 3306)、用户名(User)、密码(Password)以及目标数据库名(Database)。
- Python 3 环境:确保已安装 Python 3.7 及以上版本,并在系统终端中可调用
pip包管理工具。
1. 使用 pip 命令安装 PyMySQL
打开终端(Windows 的 PowerShell/CMD 或 macOS/Linux 的 Terminal),执行以下安装命令:
pip install pymysql
如果网络连接较慢,可指定国内镜像源进行加速:
pip install pymysql -i https://pypi.tuna.tsinghua.edu.cn/simple
2. 验证安装是否成功
在终端中直接通过一行 Python 命令测试导入与版本输出:
python -c "import pymysql; print('PyMySQL 安装成功,版本为:', pymysql.__version__)"
若屏幕正常打印出版本号(如 1.1.0 或类似版本号)且未出现 ModuleNotFoundError 错误,则说明环境已就绪。
3. 准备测试数据表
为了让后续的查询示例具有可操作性,可在 MySQL 中执行如下 SQL 语句,创建一个简单的用户表 sys_user 并插入几条测试样本:
-- 登录 MySQL 后执行
CREATE DATABASE IF NOT EXISTS demo_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE demo_db;
CREATE TABLE IF NOT EXISTS sys_user (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
status TINYINT NOT NULL DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO sys_user (username, email, status) VALUES
('zhangsan', 'zhangsan@example.com', 1),
('lisi', 'lisi@example.com', 1),
('wangwu', 'wangwu@example.com', 0);
三、核心开发流程:从建立连接到完成查询
使用 PyMySQL 查询数据的过程可细分为五个严谨的步骤:初始化连接参数、建立 Socket 握手、创建操作游标、执行 SQL 查询语句,以及按需提取结果并关闭底层资源。
四、编写完整的 Python 连接与查询代码
下面提供一份直接可运行的完整 Python 示例代码,展示如何安全连接数据库、使用字典游标查询记录,并保证发生异常时连接能被安全关闭。
import pymysql
import pymysql.cursors
def query_active_users():
# 1. 明确定义连接参数(生产环境建议通过环境变量获取)
db_config = {
'host': '127.0.0.1',
'port': 3306,
'user': 'root',
'password': 'your_password_here',
'database': 'demo_db',
'charset': 'utf8mb4',
# 将默认的元组游标替换为字典游标,返回以列名为 key 的字典
'cursorclass': pymysql.cursors.DictCursor,
'connect_timeout': 10
}
connection = None
try:
# 2. 建立 TCP 连接
print("[1/4] 正在建立 MySQL 数据库连接...")
connection = pymysql.connect(**db_config)
print("[2/4] 连接成功!")
# 3. 创建游标并执行查询(使用 with 上下文管理器确保游标自动关闭)
with connection.cursor() as cursor:
# 定义带占位符 %s 的 SQL 查询语句
sql = "SELECT id, username, email, status, created_at FROM sys_user WHERE status = %s ORDER BY id ASC"
target_status = 1
print(f"[3/4] 正在执行查询: {sql} | 参数: {(target_status,)}")
# execute() 接收两个参数:SQL 模板与实参元组
cursor.execute(sql, (target_status,))
# 4. 获取查询结果集
# fetchall() 返回由所有匹配行构成的列表
rows = cursor.fetchall()
print(f"[4/4] 查询完成,共获取到 {len(rows)} 条记录:")
for row in rows:
print(f" 用户ID: {row['id']} | 用户名: {row['username']} | 邮箱: {row['email']}")
# 如果只需要匹配的第一条,可以使用 fetchone()
cursor.execute("SELECT id, username FROM sys_user WHERE id = %s", (1,))
first_user = cursor.fetchone()
if first_user:
print(f" 精确单条查询结果 -> ID: {first_user['id']}, Name: {first_user['username']}")
except pymysql.MySQLError as err:
print(f"数据库操作发生异常: {err}")
finally:
# 5. 必须在 finally 块中关闭连接,避免连接资源泄漏
if connection and connection.open:
connection.close()
print("底层数据库连接已安全关闭。")
if __name__ == '__main__':
query_active_users()
charset='utf8mb4':MySQL 中的传统utf8仅支持最多 3 字节字符,当数据中包含 Emoji 表情或特殊汉字时会导致插入崩溃。因此在 Python 与 MySQL 通信时,必须统一指定为 utf8mb4。cursorclass=pymysql.cursors.DictCursor:默认情况下游标返回的是纯 Python 元组(Tuple),如(1, 'zhangsan'),字段只能靠下标访问;使用DictCursor后,单行记录以字典形式返回(如{'id': 1, 'username': 'zhangsan'}),极大提升代码可维护性。
五、核心机制与关键安全防护:参数化查询
在编写数据库查询时,最容易出现的严重缺陷就是直接使用 Python 的字符串格式化(如 f-string、+ 拼接或 % 运算符)拼装 SQL。直接拼接不仅会破坏 SQL 语句结构,还会导致灾难性的 SQL 注入漏洞(SQL Injection)。
在 PyMySQL 中,占位符无论对应的数据类型是整数、浮点数还是字符串,统一使用 %s,不要在 SQL 模板中的 %s 外围添加额外的单引号(如 '%s' 是多余且错误的)。
# 规范做法:单个参数时使用单元素元组 (val,) 或列表 [val]
cursor.execute("SELECT * FROM sys_user WHERE id = %s", (user_id,))
# 多个参数时按顺序传入元组
cursor.execute("SELECT * FROM sys_user WHERE status = %s AND email LIKE %s", (1, '%@example.com'))
六、结果集读取方法深度对比
游标在执行 execute() 后,会与 MySQL 服务端建立数据流通道。根据数据规模与业务场景,PyMySQL 提供了三种常用的提取方法:
| 提取方法 | 返回值类型 | 适用场景 | 内存表现 |
|---|---|---|---|
cursor.fetchone() |
单条记录(Dict 或 Tuple)或 None |
根据主键或唯一索引查找单条数据,或分步循环处理 | 极低,仅缓存单行数据 |
cursor.fetchall() |
包含全部匹配记录的列表(List) | 数据量已知且较小(通常小于 5000 行)的常规查询 | 将所有结果一次性载入 Python 内存 |
cursor.fetchmany(size) |
指定最大数量的记录列表 | 分页批量流式处理(如数据清洗、批量同步) | 按分块控制内存峰值 |
七、常见连接报错与排查清单
初学者在配置 Python 连接 MySQL 时,经常会遇到各类网络与鉴权异常。以下是四类最核心的报错原因及对应排查步骤:
八、教程总结
回顾本文的核心内容,Python 连接与操作 MySQL 数据库的整个链条其实非常清晰:
- 安装阶段:利用
pip install pymysql安装纯 Python 驱动,无须本地编译依赖。 - 连接阶段:通过
pymysql.connect()建立网络连接,重点指定charset='utf8mb4'及cursorclass=pymysql.cursors.DictCursor。 - 查询阶段:采用
cursor.execute(sql, params)执行参数化查询,从根本上隔离指令与用户输入,彻底杜绝 SQL 注入隐患。 - 清理阶段:始终在
finally块中调用connection.close(),或结合上下文管理器自动释放连接资源。
掌握了上述基础与安全规范后,无论是后续开发日常的数据导出工具、编写自动化监控任务,还是接入 DBUtils 连接池与 SQLAlchemy ORM 框架,你都将具备扎实可靠的底层基础。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









