Python连接MySQL:PyMySQL入门与实践指南
1. PyMySQL基础入门与安装指南
PyMySQL是Python3中用于连接MySQL数据库的纯Python驱动库,它实现了Python数据库API规范2.0版本。与Python2时代广泛使用的MySQLdb不同,PyMySQL完全用Python编写,不需要编译任何C扩展模块,这使得它在跨平台部署时更加方便。
1.1 PyMySQL的核心特性
PyMySQL具有以下几个显著特点:
- 纯Python实现,无需编译安装
- 支持Python3(Python2可使用MySQLdb)
- 实现了Python DB API 2.0规范
- 支持SSL安全连接
- 包含连接池支持
- 兼容大多数MySQL特性,包括存储过程、事务等
在实际项目中,我发现PyMySQL相比其他MySQL连接器有几个优势:首先,它的安装过程非常简单,特别是对于没有编译环境的Windows用户;其次,它的错误信息更加友好,调试起来更方便;最后,由于是纯Python实现,可以方便地查看源码理解内部机制。
1.2 安装PyMySQL的多种方式
安装PyMySQL最常用的方式是通过pip:
pip install pymysql如果你需要安装特定版本,可以指定版本号:
pip install pymysql==1.0.2在某些特殊环境下,可能需要从源码安装。这时可以克隆GitHub仓库:
git clone https://github.com/PyMySQL/PyMySQL cd PyMySQL python setup.py install注意:从源码安装需要确保系统已安装setuptools。如果遇到"ImportError: No module named setuptools"错误,需要先安装setuptools。
在Linux系统上,可以通过以下命令安装setuptools:
wget https://bootstrap.pypa.io/ez_setup.py python ez_setup.py2. 数据库连接与基本操作
2.1 建立数据库连接
使用PyMySQL连接MySQL数据库的基本代码如下:
import pymysql # 创建数据库连接 connection = pymysql.connect( host='localhost', # 数据库服务器地址 user='username', # 数据库用户名 password='password', # 数据库密码 database='dbname', # 数据库名 port=3306, # 端口,默认为3306 charset='utf8mb4', # 字符集 cursorclass=pymysql.cursors.DictCursor # 使用字典游标 ) try: with connection.cursor() as cursor: # 执行SQL查询 sql = "SELECT * FROM users WHERE id = %s" cursor.execute(sql, (1,)) # 获取查询结果 result = cursor.fetchone() print(result) finally: # 关闭连接 connection.close()在实际项目中,我建议将数据库连接信息存储在配置文件中,而不是硬编码在代码里。这样可以方便地在不同环境(开发、测试、生产)之间切换。
2.2 使用上下文管理器简化连接管理
Python的with语句可以简化连接管理,确保连接在使用后被正确关闭。我们可以封装一个数据库上下文管理器:
import pymysql from contextlib import contextmanager @contextmanager def get_db_connection(): conn = pymysql.connect( host='localhost', user='user', password='pass', database='db', charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor ) try: yield conn finally: conn.close() # 使用示例 with get_db_connection() as conn: with conn.cursor() as cursor: cursor.execute("SELECT * FROM products") results = cursor.fetchall() for row in results: print(row)这种写法不仅代码更简洁,而且能确保在任何情况下(包括发生异常时)数据库连接都会被正确关闭,避免资源泄漏。
3. 执行SQL查询与事务处理
3.1 基本CRUD操作
PyMySQL支持所有标准的SQL操作,包括增删改查(CRUD)。下面是一些常见操作的示例:
查询数据:
with connection.cursor() as cursor: # 查询单条记录 cursor.execute("SELECT * FROM users WHERE id = %s", (1,)) user = cursor.fetchone() # 查询多条记录 cursor.execute("SELECT * FROM users WHERE status = %s", ('active',)) active_users = cursor.fetchall() # 获取记录数量 cursor.execute("SELECT COUNT(*) FROM users") user_count = cursor.fetchone()['COUNT(*)']插入数据:
try: with connection.cursor() as cursor: sql = "INSERT INTO users (name, email) VALUES (%s, %s)" cursor.execute(sql, ('John Doe', 'john@example.com')) # 提交事务 connection.commit() except: # 发生错误时回滚 connection.rollback() raise更新数据:
try: with connection.cursor() as cursor: sql = "UPDATE users SET name = %s WHERE id = %s" cursor.execute(sql, ('John Smith', 1)) print(f"更新了{cursor.rowcount}条记录") connection.commit() except: connection.rollback() raise删除数据:
try: with connection.cursor() as cursor: sql = "DELETE FROM users WHERE id = %s" cursor.execute(sql, (1,)) connection.commit() except: connection.rollback() raise3.2 事务处理
MySQL支持事务,PyMySQL也提供了完整的事务支持。事务的四个特性(ACID)是:
- 原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不完成
- 一致性(Consistency):事务执行前后,数据库从一个一致状态变为另一个一致状态
- 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务
- 持久性(Durability):事务一旦提交,其结果就是永久性的
在PyMySQL中,默认情况下每个SQL语句都会自动提交。要使用事务,需要先关闭自动提交:
connection = pymysql.connect( host='localhost', user='user', password='pass', database='db', autocommit=False # 关闭自动提交 ) try: with connection.cursor() as cursor: # 执行多个SQL语句 cursor.execute("UPDATE accounts SET balance = balance - 100 WHERE id = 1") cursor.execute("UPDATE accounts SET balance = balance + 100 WHERE id = 2") # 手动提交事务 connection.commit() except: # 发生错误时回滚 connection.rollback() raise finally: connection.close()在实际项目中,我发现事务的正确使用非常重要。特别是在处理金融交易、库存管理等场景时,一定要确保事务的完整性和一致性。
4. 高级特性与最佳实践
4.1 批量操作与参数化查询
PyMySQL支持批量插入和更新操作,这可以显著提高性能:
# 批量插入 data = [ ('John', 'john@example.com'), ('Jane', 'jane@example.com'), ('Bob', 'bob@example.com') ] with connection.cursor() as cursor: sql = "INSERT INTO users (name, email) VALUES (%s, %s)" cursor.executemany(sql, data) connection.commit()参数化查询不仅可以防止SQL注入,还能提高性能(因为MySQL可以缓存编译后的语句):
# 不安全的写法(容易受到SQL注入攻击) cursor.execute("SELECT * FROM users WHERE id = " + user_input) # 安全的参数化查询 cursor.execute("SELECT * FROM users WHERE id = %s", (user_input,))4.2 错误处理与异常管理
PyMySQL定义了多种数据库操作相关的异常,合理的错误处理可以使程序更加健壮:
try: with connection.cursor() as cursor: cursor.execute("SELECT * FROM non_existent_table") except pymysql.err.ProgrammingError as e: print(f"SQL语法错误: {e}") except pymysql.err.OperationalError as e: print(f"数据库操作错误: {e}") except Exception as e: print(f"其他错误: {e}")常见的PyMySQL异常包括:
ProgrammingError:SQL语法错误OperationalError:数据库操作错误(如连接失败)IntegrityError:完整性约束错误(如重复键)DataError:数据处理错误(如数据超出范围)
4.3 连接池与性能优化
对于高并发应用,频繁创建和关闭数据库连接会影响性能。可以使用连接池来管理数据库连接:
from pymysql import pools # 创建连接池 pool = pools.Pool( host='localhost', user='user', password='pass', database='db', min=2, # 最小连接数 max=10, # 最大连接数 autocommit=False ) # 从连接池获取连接 connection = pool.connection() try: with connection.cursor() as cursor: cursor.execute("SELECT * FROM users") results = cursor.fetchall() finally: # 将连接返回连接池 connection.close()其他性能优化建议:
- 合理使用索引加速查询
- 避免在循环中执行SQL语句
- 只查询需要的列,避免SELECT *
- 对于大量数据,考虑使用分页查询
4.4 使用ORM与PyMySQL结合
虽然PyMySQL提供了直接的SQL接口,但在大型项目中,使用ORM(对象关系映射)框架可以使代码更加清晰:
from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker # 创建SQLAlchemy引擎(底层使用PyMySQL) engine = create_engine('mysql+pymysql://user:pass@localhost/db') # 创建Session工厂 Session = sessionmaker(bind=engine) # 使用Session session = Session() try: # 执行查询 users = session.execute("SELECT * FROM users") for user in users: print(user) finally: session.close()在实际项目中,我发现对于简单的查询,直接使用PyMySQL更高效;而对于复杂的业务逻辑,使用ORM可以提高开发效率和代码可维护性。