在 Python 开发中,连接 MySQL 数据库是处理持久化数据的常见任务。无论是 Web 后端、数据分析脚本,还是自动化运维工具,经常都需要把数据写入数据库,或者从数据库中读取结果。实现这一目标的关键,是选择稳定的数据库驱动并正确使用连接、游标、执行、提交和关闭等步骤。当前在 Python 3 环境下,PyMySQL 是常用且稳定的选择,它通过标准接口与 MySQL 服务通信,适合中小型项目以及日常数据处理场景。

连接 MySQL 前的准备与驱动选择
开始编写代码之前,首先要确认本地或远程 MySQL 服务已经启动,并且能够访问对应的数据库。连接数据库通常需要掌握几项基本信息:主机地址、端口、用户名、密码以及目标数据库名称。如果服务运行在本机,主机地址通常可以写成 127.0.0.1,端口通常使用 MySQL 默认端口 3306。若数据库部署在远程服务器,则需要填写服务器地址,并确认防火墙、安全组和账号权限允许该来源连接。
在驱动层面,PyMySQL 是一个纯 Python 实现的客户端库,安装过程简单,依赖关系较少。通过包管理工具安装后,就可以在脚本中导入该模块并创建连接对象。对于大多数基础场景,只需要安装驱动即可开始使用;如果项目涉及连接池、ORM 或更复杂的部署方式,则可以在这个基础上继续扩展,但连接数据库的基本原理仍然一致。
连接参数中有一个容易被忽略的选项是字符集。建议将字符集设置为 utf8mb4,这样可以更完整地支持中文、符号以及更多 Unicode 字符,减少因编码不一致导致的数据乱码或写入失败问题。将连接参数集中放到一个字典中,可以提高代码可读性,也便于后续从配置文件或环境变量中读取真实参数。
# 安装 PyMySQL 驱动 pip install pymysql
使用 PyMySQL 完成基础连接与查询
使用 PyMySQL 连接 MySQL 的基本流程可以概括为五个步骤:创建连接对象、创建游标对象、执行 SQL 语句、获取处理结果、关闭游标和连接。连接对象代表与数据库服务的一次会话,游标对象则用于在当前会话中执行语句和读取结果。查询类语句执行后,可以通过 fetchone、fetchall 或 fetchmany 获取不同数量的结果;修改类语句执行后,通常还需要提交事务,数据才会真正落库。
在编写连接代码时,建议把数据库操作放入异常处理结构中。因为网络波动、账号密码错误、数据库不存在、表结构不匹配等问题都可能导致异常。捕获 PyMySQL 提供的数据库异常后,程序可以输出错误信息并执行回滚或清理动作,而不是直接中断。这样不仅便于定位问题,也能让脚本在失败时保持可控状态。
下面的示例演示了最基础的连接方式:程序先读取配置字典,再创建连接和游标,然后执行查询数据库版本的 SQL 语句,最后输出结果并关闭资源。这个例子虽然简单,但覆盖了连接、执行、取结果和释放资源四个关键环节,适合作为后续复杂操作的基础模板。
import pymysql
# 定义数据库连接参数
db_config = {
'host': '127.0.0.1',
'port': 3306,
'user': 'root',
'password': '123456',
'database': 'test_db',
'charset': 'utf8mb4'
}
try:
# 建立数据库连接
conn = pymysql.connect(**db_config)
# 创建游标对象,用于执行 SQL 语句
cursor = conn.cursor()
# 执行查询数据库版本的 SQL
cursor.execute('SELECT VERSION()')
# 获取单条查询结果
result = cursor.fetchone()
print('MySQL 版本:', result[0])
except pymysql.MySQLError as e:
print('数据库连接或查询失败:', e)
finally:
# 关闭游标和连接,释放资源
if 'cursor' in locals():
cursor.close()
if 'conn' in locals():
conn.close()
常见数据操作与事务处理
新增、修改和删除数据时,SQL 语句本身只是把变更发送到数据库,真正让变更持久化通常需要提交事务。PyMySQL 中可以通过连接对象的 commit 方法提交当前事务;如果执行过程中发生异常,则可以使用 rollback 方法回滚未提交的变更。事务处理能够保证数据变更的完整性,避免程序中途失败后留下半完成状态。
执行数据变更后,可以通过游标的 rowcount 属性查看本次操作影响的行数。这个属性在新增、更新和删除场景中都很常用,可以用于判断操作是否命中数据,也可以作为日志记录的一部分。需要注意的是,rowcount 反映的是当前游标最近一次执行语句的影响情况,因此在连续执行多条语句时,最好及时保存或输出对应的结果,避免混淆。
查询数据时,游标类型会影响返回结果的组织方式。默认游标通常返回元组,适合按位置取值;字典游标则会把每一行组织成字典,适合按字段名访问。对于字段较多或业务含义较强的表,使用字典游标可以让代码更清晰,减少因字段顺序变化带来的错误。下面分别展示新增、查询、修改和删除的基本写法,这些示例都保留了异常处理和资源关闭逻辑。
import pymysql
db_config = {
'host': '127.0.0.1',
'port': 3306,
'user': 'root',
'password': '123456',
'database': 'test_db',
'charset': 'utf8mb4'
}
try:
conn = pymysql.connect(**db_config)
cursor = conn.cursor()
# 新增一条用户数据
insert_sql = "INSERT INTO user (name, age) VALUES ('张三', 25)"
cursor.execute(insert_sql)
# 提交事务,使新增数据真正写入数据库
conn.commit()
print('新增成功,影响行数:', cursor.rowcount)
except pymysql.MySQLError as e:
# 出错时回滚事务
if 'conn' in locals():
conn.rollback()
print('新增失败:', e)
finally:
if 'cursor' in locals():
cursor.close()
if 'conn' in locals():
conn.close()
import pymysql
db_config = {
'host': '127.0.0.1',
'port': 3306,
'user': 'root',
'password': '123456',
'database': 'test_db',
'charset': 'utf8mb4'
}
try:
conn = pymysql.connect(**db_config)
# 使用字典游标,查询结果按字段名访问
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 查询年龄大于 20 的用户
query_sql = 'SELECT id, name, age FROM user WHERE age > 20'
cursor.execute(query_sql)
# 获取全部结果
results = cursor.fetchall()
for row in results:
print('用户ID:', row['id'], '姓名:', row['name'], '年龄:', row['age'])
except pymysql.MySQLError as e:
print('查询失败:', e)
finally:
if 'cursor' in locals():
cursor.close()
if 'conn' in locals():
conn.close()
import pymysql
db_config = {
'host': '127.0.0.1',
'port': 3306,
'user': 'root',
'password': '123456',
'database': 'test_db',
'charset': 'utf8mb4'
}
try:
conn = pymysql.connect(**db_config)
cursor = conn.cursor()
# 修改指定用户的年龄
update_sql = "UPDATE user SET age = 26 WHERE name = '张三'"
cursor.execute(update_sql)
update_count = cursor.rowcount
# 删除年龄小于 18 的用户
delete_sql = 'DELETE FROM user WHERE age < 18'
cursor.execute(delete_sql)
delete_count = cursor.rowcount
# 提交事务
conn.commit()
print('修改影响行数:', update_count)
print('删除影响行数:', delete_count)
except pymysql.MySQLError as e:
# 出错时回滚事务
if 'conn' in locals():
conn.rollback()
print('修改或删除失败:', e)
finally:
if 'cursor' in locals():
cursor.close()
if 'conn' in locals():
conn.close()
资源管理、异常处理与生产实践
数据库连接是一种有限资源,长时间占用会消耗数据库连接数,也可能影响服务稳定性。因此在操作完成后,应当及时关闭游标和连接。除了手动在 finally 中关闭之外,还可以使用上下文管理器,让 with 语句在代码块结束时自动释放资源。这种方式可以减少遗漏关闭的情况,也让代码结构更加简洁。
异常处理是生产代码中不可缺少的部分。数据库操作可能受到网络、权限、锁等待、语法错误等多种因素影响,直接让异常抛出通常不是理想做法。合理捕获异常后,可以记录日志、回滚事务、返回友好提示,必要时再触发告警。对于自动化脚本而言,稳定的错误处理能够避免程序在关键步骤崩溃,也方便后续排查。
在参数管理方面,生产环境不建议把数据库密码明文写在代码文件中。更安全的做法是把主机、端口、账号、密码和数据库名放到配置文件、环境变量或配置中心中,代码只负责读取这些值。这样既降低了敏感信息泄露风险,也便于在不同环境之间切换。结合字符集设置、事务提交、异常捕获和资源释放,就能构建一套较为可靠的 Python 连接 MySQL 的基本实践。
import pymysql
db_config = {
'host': '127.0.0.1',
'port': 3306,
'user': 'root',
'password': '123456',
'database': 'test_db',
'charset': 'utf8mb4'
}
# 使用上下文管理器自动管理连接和游标资源
with pymysql.connect(**db_config) as conn:
with conn.cursor() as cursor:
cursor.execute('SELECT id, name, age FROM user')
rows = cursor.fetchall()
for row in rows:
print(row)
综合来看,Python 连接 MySQL 的核心并不复杂,重点在于把连接参数配置准确、把 SQL 执行放在异常处理中、把事务提交和资源释放处理完整。掌握基础连接、查询、新增、修改和删除操作后,再结合字符集设置、错误回滚和上下文管理器,就能在脚本、工具或 Web 项目中稳定地读写 MySQL 数据。