Python 数据访问:PyMySQL 与 SQLAlchemy 入门

集中整理 Python 项目里的数据访问主线:先用 PyMySQL 理解连接与事务,再用 SQLAlchemy 建立 ORM 认知。

这篇文章只回答一件事:Python 程序该如何与关系型数据库打交道。

一、先区分两个角色

  • MySQL:关系型数据库,负责结构化数据持久化
  • ORM:对象关系映射,让你用对象方式操作数据库,而不是频繁手写 SQL

可以先记住一句话:

  • 先会手写 SQL,你才知道 ORM 在帮你抽象什么
  • 学会 ORM,你才知道大型项目为什么不愿到处散落 SQL

二、使用 PyMySQL 连接 MySQL

pymysql 到今天依然是常见方案之一。

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",
    port=3306,
    user="root",
    password="your-password",
    database="demo",
    charset="utf8mb4",
)

try:
    with conn.cursor() as cursor:
        cursor.execute(
            "INSERT INTO user (name, password) VALUES (%s, %s)",
            ("alex", "123456"),
        )
    conn.commit()
except Exception:
    conn.rollback()
    raise
finally:
    conn.close()

查询示例

import pymysql

conn = pymysql.connect(
    host="127.0.0.1",
    port=3306,
    user="root",
    password="your-password",
    database="demo",
    charset="utf8mb4",
    cursorclass=pymysql.cursors.DictCursor,
)

try:
    with conn.cursor() as cursor:
        cursor.execute("SELECT id, name FROM user")
        rows = cursor.fetchall()
        for row in rows:
            print(row)
finally:
    conn.close()

先记住这几个原则

  • 写操作后记得 commit()
  • 写操作如果中途失败,记得 rollback()
  • 优先使用参数化 SQL
  • 连接和游标都要及时关闭
  • 查询结果常见方法是 fetchone()fetchmany()fetchall()

三、为什么还要学习 ORM

当业务逐渐复杂时,手写 SQL 会开始暴露这些问题:

  • 表结构和代码模型之间缺少统一映射
  • 常见增删改查重复度高
  • 关系查询表达不一致
  • 大量 SQL 分散在不同模块里,维护成本上升

这时 ORM 的价值就出来了。

常见选择可以简单理解成:

  • 独立 Python 项目:常见选择是 SQLAlchemy
  • Django 项目:通常直接使用 Django ORM

四、SQLAlchemy 的最小认知

Classic 映射和 Declarative 映射怎么理解

旧版 SQLAlchemy 常见 Classic 映射:

  • 先单独描述表
  • 再把 Python 类映射到表

例如:

from sqlalchemy import Column, Integer, MetaData, String, Table

metadata = MetaData()
user_table = Table(
    "users",
    metadata,
    Column("id", Integer, primary_key=True),
    Column("name", String(50)),
    Column("fullname", String(50)),
)

这有助于理解 ORM 的本质,但在今天的新项目里,更推荐声明式写法。

更推荐的 DeclarativeBase

from sqlalchemy import String, create_engine, select
from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column


class Base(DeclarativeBase):
    pass


class User(Base):
    __tablename__ = "user"

    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(String(32))
    password: Mapped[str] = mapped_column(String(64))


engine = create_engine(
    "mysql+pymysql://root:password@127.0.0.1/demo?charset=utf8mb4"
)

with Session(engine) as session:
    session.add(User(name="alex", password="123456"))
    session.commit()

    rows = session.execute(select(User)).scalars().all()
    for row in rows:
        print(row.name, row.password)

常见操作对应关系

  • 新增:session.add(obj) 然后 session.commit()
  • 查询:session.execute(select(User).filter(...)).scalars().all()
  • 修改:先查对象,再改字段,再 commit()
  • 删除:session.delete(obj) 或构造删除语句

五、该先学 SQL 还是先学 ORM

更稳妥的顺序通常是:

  1. 先用 PyMySQL 熟悉连接、事务和参数化 SQL
  2. 再学 ORM,理解对象化操作数据库的价值
  3. 最后根据框架或团队栈选择 SQLAlchemy / Django ORM

这样做的好处是,你不会把 ORM 当成“魔法”。

六、实战建议

  • 不要把 ORM 当成“不用懂 SQL”的借口
  • 一旦遇到复杂查询,仍然要能读懂底层 SQL
  • 写入逻辑要关注事务边界
  • 表结构设计和代码模型设计要保持一致
  • 在中文环境下,字符集优先确认 utf8mb4

小结

数据访问这一层,可以先抓住三句话:

  • MySQL 负责存数据
  • PyMySQL 帮你直接执行 SQL
  • ORM 帮你把数据库操作组织得更可维护

把这条主线理解清楚,再进入 Web 框架或后台系统开发时,会顺很多。

相关阅读

  • 《Python 消息队列与任务系统》:异步任务、队列与调度的另一条主线
  • 《Python 网络与并发》:理解并发执行模型和系统拆分背景