0Pricing
Python Academy · 课时

事务与上下文管理器

安全地提交和回滚

事务与上下文管理器 是 CoddyKit 上的免费 Python Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Python Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Python Academy 课程共包含 4 节课。

什么是事务

事务会将多条语句组合起来,使它们要么全部成功,要么全部一起失败。这样可以保持数据一致。

SQLite 会在执行更改数据的语句之前自动开始事务。

import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance INTEGER)')
print('Table ready for transactions')
conn.close()

提交以保存

在调用 conn.commit() 之前,更改都不是永久的。在此之前,它们只存在于当前事务中。

import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance INTEGER)')
cur.execute('INSERT INTO accounts (balance) VALUES (100)')
conn.commit()
print('Committed')
conn.close()

回滚

conn.rollback() 会撤销自上次提交以来的所有更改。当出现问题时,请使用它。

import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance INTEGER)')
conn.commit()
cur.execute('INSERT INTO accounts (balance) VALUES (100)')
conn.rollback()
cur.execute('SELECT COUNT(*) FROM accounts')
print('Rows after rollback:', cur.fetchone()[0])
conn.close()

转账

当多项更新必须保持同步时,事务的作用尤为明显。银行转账会从一个账户扣款,并向另一个账户入账。这两个操作必须同时发生,否则就都不能发生。

import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance INTEGER)')
cur.execute('INSERT INTO accounts (id, balance) VALUES (1, 100)')
cur.execute('INSERT INTO accounts (id, balance) VALUES (2, 50)')
cur.execute('UPDATE accounts SET balance = balance - 30 WHERE id = 1')
cur.execute('UPDATE accounts SET balance = balance + 30 WHERE id = 2')
conn.commit()
cur.execute('SELECT id, balance FROM accounts')
print(cur.fetchall())
conn.close()

使用 try/except 处理错误

请将事务放在 try/except 中。当发生错误时,执行回滚,以免部分更改破坏数据。

import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance INTEGER)')
try:
    cur.execute('INSERT INTO accounts (id, balance) VALUES (1, 100)')
    cur.execute('INSERT INTO accounts (id, balance) VALUES (1, 200)')
    conn.commit()
except sqlite3.IntegrityError:
    conn.rollback()
    print('Rolled back after error')
conn.close()

作为上下文管理器的连接

使用 with conn: 会在成功时自动提交;如果代码块内部发生异常,则会自动回滚。

import sqlite3
conn = sqlite3.connect(':memory:')
conn.execute('CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance INTEGER)')
with conn:
    conn.execute('INSERT INTO accounts (balance) VALUES (100)')
print('Auto-committed via with block')
conn.close()

异常时自动回滚

如果 with conn: 代码块引发异常,事务会自动回滚。请注意,连接本身仍保持打开状态。

import sqlite3
conn = sqlite3.connect(':memory:')
conn.execute('CREATE TABLE accounts (id INTEGER PRIMARY KEY)')
try:
    with conn:
        conn.execute('INSERT INTO accounts (id) VALUES (1)')
        conn.execute('INSERT INTO accounts (id) VALUES (1)')
except sqlite3.IntegrityError:
    print('Block rolled back automatically')
count = conn.execute('SELECT COUNT(*) FROM accounts').fetchone()[0]
print('Rows:', count)
conn.close()

使用 closing() 处理连接

contextlib.closing 辅助工具保证在代码块结束时调用 close(),从而释放连接。

import sqlite3
from contextlib import closing
with closing(sqlite3.connect(':memory:')) as conn:
    conn.execute('CREATE TABLE t (id INTEGER)')
    print('Used inside closing()')
print('Connection closed automatically')

结合两种模式

将 with conn: 嵌套在 closing(...) 中,同时管理事务并确保连接关闭。

import sqlite3
from contextlib import closing
with closing(sqlite3.connect(':memory:')) as conn:
    conn.execute('CREATE TABLE t (id INTEGER, v TEXT)')
    with conn:
        conn.execute('INSERT INTO t VALUES (1, ?)', ('hello',))
    print(conn.execute('SELECT * FROM t').fetchall())

isolation_level

连接的 isolation_level 控制事务何时开始。默认设置让 SQLite 管理事务;将其设为 None 可启用自动提交模式。

import sqlite3
conn = sqlite3.connect(':memory:')
print('Default isolation_level:', repr(conn.isolation_level))
conn.isolation_level = None
print('Now autocommit:', conn.isolation_level)
conn.close()

事务为何重要

没有事务时,中途发生崩溃可能会留下只完成一半的数据。事务会使一组更改具有原子性:不可分割。这可以保护数据完整性。

import sqlite3
conn = sqlite3.connect(':memory:')
conn.execute('CREATE TABLE log (msg TEXT)')
with conn:
    conn.execute('INSERT INTO log VALUES (?)', ('all or nothing',))
print('Atomic write done')
conn.close()

快速检查

测试您对事务的了解。

回顾

您已经学会安全地管理事务。

  • commit() 保存更改;rollback() 撤销更改
  • 使用带回滚的 try/except 包裹有风险的写入操作
  • with conn: 会自动提交或自动回滚
  • contextlib.closing 保证连接关闭

常见问题解答

「事务与上下文管理器」课时是免费的吗?

是的 — 「事务与上下文管理器」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Python Academy 课程的其余内容,请升级到 CoddyKit PRO。 Python Academy 课程共包含 4 节课。

「事务与上下文管理器」这节课中我会学到什么?

安全地提交和回滚 你通过在浏览器中直接运行的动手代码来练习 Python Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Python Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Python Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「事务与上下文管理器」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Python Academy 课中编写并运行代码吗?

能。每节 Python Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 连接数据库并创建表
  2. 插入、查询、更新、删除
  3. 参数化查询
  4. 事务与上下文管理器
← 返回 Python Academy