如题,本文记录如何使用python上下文管理器的方式管理sqlite3的句柄创建和释放以及事务机制。

1、python上下文管理(with)

python上下文管理(context),解决的是这样一类问题,在进入逻辑之前需要进行一些准备工作,在退出逻辑之前需要进行一些善后工作,上下文管理可以使得这种场景变得清晰和可控。

with语句是python上下文管理的基本用法,例如读写文件

with open('filea', r) as f:
f.readlines()

file使用的就是上下文管理机制,这样对于打开文件句柄和释放文件句柄无须我们额外的投入精力。

2、sqlite3

sqlite3是一个嵌入式的文件数据库,无须开启额外的进程和端口,就可以通过文件读取的方式实现数据库的操作。优点是轻量级并且支持事务和触发器等高级特性。

sqlite3在python句柄创建和管理上跟mysql表现的很相似。

3、代码

我们先贴上本文简述的这段代码,然后后面我们在做详细解释。

# -*- coding:utf-8 -*-
import sqlite3
import traceback class SqliteDB(object): def __init__(self, database='sqlitedb', isolation_level='', ignore_exc=False):
self.database = database
self.isolation_level = isolation_level
self.ignore_exc = ignore_exc
self.connection = None
self.cursor = None def __enter__(self):
try:
self.connection = sqlite3.connect(database=self.database, isolation_level=self.isolation_level)
self.cursor = self.connection.cursor()
return self.cursor
except Exception, ex:
traceback.print_exc()
raise ex def __exit__(self, exc_type, exc_val, exc_tb):
try:
if not exc_type is None:
self.connection.rollback()
return self.ignore_exc
else:
self.connection.commit()
except Exception, ex:
traceback.print_exc()
raise ex
finally:
self.cursor.close()
self.connection.close()

我们给出一个使用的case

if __name__ == '__main__':
# 建表
with SqliteDB('test') as db:
db.execute('create table if not exists user (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(100), age INTEGER)') # 创建一条记录, 如果抛出异常, 可以测试事务回滚
with SqliteDB('test') as db:
db.execute('insert into user (name, age) values (?, ?)', ('Tom', 10))
#raise Exception() # 查询记录
with SqliteDB('test') as db:
query_set = db.execute('select * from user where name=? limit ?', ('Tom', 100,)).fetchall()
print len(query_set)
for item in query_set:
print item # 删除记录
with SqliteDB('test') as db:
query_set = db.execute('delete from user where name=?', ('Tom',))

可以看到通过with语句打开了数据库的句柄,执行数据库操作后,我们并没有管理句柄的释放和事务回滚。

代码的输出是:

1
(6, u'Tom', 10)

当打开raise Exception()的注释,表示在插入的过程中遇到了异常。这时候所有connection中未被提交的数据将被回滚。

那么,这些如何做到的呢?

上下文管理是通过类SqliteDB中的__enter__和__exit__两个魔法函数实现的。

1、enter函数,用来实现处理进入with_body之前的准备工作,这里是创建connect和cursor,enter方法返回了cursor。

enter函数如果有返回值,那么可以赋值给as后面的变量,如果没有返回,可以简单的去掉as子句即可。我们给出一个没有as子句的例子

lock = threading.Lock()
with lock:
pass

如果enter函数抛出异常,那么在执行with语句的时候会抛出这个异常,并且中断程序。

2、逻辑上,enter函数之后,便开始执行with_body内的代码,with_body里的代码包含sql语句和一些业务逻辑,这里说明一下,只要是抛出异常就会触发事务的回滚机制,而不会区分到底是sql语句执行异常还是业务逻辑出现的异常。

3、exit函数,在with_body执行成功或者抛出异常后会执行exit函数。

exit函数传入三个变量,分别是exc_type异常类型,exc_val异常值,exc_tb错误堆栈信息。如果程序正常,那么三个值都是None,相反如果不是None,那么可以就此判断with_body产生了异常。

这里,我们判断了exc_type是否为None,来区分是否抛出了异常,如果抛出了异常我们使用connection.rollback进行了事务的回滚,否则我们使用connection.commit进行事务提交。

要注意的是,在出现异常的时候,返回了一个ignore_exc,这个返回如果是True,表示忽略这个异常,这个异常将不会向上级调用抛出,如果返回的是None或者False,异常将会向上抛出。实际中我们还是希望异常能够跑出来,方便处理,所以这里我们默认为False。

注意:

isolation_level这个字段是隔离级别,这里我们不做深入的说明。需要知道的是这个字段

1)传入空字符串‘’,表示手动提交commit,这时需要程序中显示的执行connection.commit进行事务提交,sql中的dml语句才会生效。

2)传入None,表示开启自动提交,这时候自动提交commit,无需在程序中connection.commit进行事务提交。

python使用上下文管理器实现sqlite3事务机制的更多相关文章

  1. 谈一谈Python的上下文管理器

    经常在Python代码中看到with语句,仔细分析下,会发现这个with语句功能好强,可以自动关闭资源.这个在Python中叫上下文管理器Context Manager.那我们要怎么用它,什么时候用它 ...

  2. Python 的上下文管理器是怎么设计的?

    花下猫语:最近,我在看 Python 3.10 版本的更新内容时,发现有一个关于上下文管理器的小更新,然后,突然发现上下文管理器的设计 PEP 竟然还没人翻译过!于是,我断断续续花了两周时间,终于把这 ...

  3. python contextlib 上下文管理器

    1.with操作符 在python中读写文件,可能需要这样的代码 try-finally读写文件 file_text = None try: file_text = open('./text', 'r ...

  4. 【Python】 上下文管理器和contextlib

    上下文管理器 一直对python中的上下文管理比较迷惑,趁着今天研究SQLAlchemy顺便看了一下,感觉稍微清楚了一点.http://www.cnblogs.com/chenny7/p/421344 ...

  5. python 黑魔法 ---上下文管理器(contextor)

    所谓上下文 计算机上下文(Context)对于我而言,一直是一个很抽象的名词.就像形而上一样,经常听见有人说,但是无法和现实认知世界相结合. 最直观的上下文,莫过于小学的语文课,经常会问联系上下文,推 ...

  6. python的上下文管理器-1

    reference:https://zhuanlan.zhihu.com/p/26487659 来看看如何正确关闭一个文件. 普通版: def m1(): f = open("output. ...

  7. python的上下文管理器

    直接上代码: f = open('123.txt','w') try: f.write('hello world') except Exception: pass finally: f.close() ...

  8. 【Python】【上下文管理器】

    """#[备注]#1⃣️try :仅当try块中没有异常抛出时才运行else块.#2⃣️for:仅当for循环运行完毕(即for循环没有被break语句终止)才运行els ...

  9. 【Python学习笔记】with语句与上下文管理器

    with语句 上下文管理器 contextlib模块 参考引用 with语句 with语句时在Python2.6中出现的新语句.在Python2.6以前,要正确的处理涉及到异常的资源管理时,需要使用t ...

随机推荐

  1. SVM公式推导笔记

    参考资料: 对偶函数-http://blog.pluskid.org/?p=702 KTT和拉格朗日乘子-http://www.cnblogs.com/zhangchaoyang/articles/2 ...

  2. 使用TensorFlow中的Batch Normalization

    问题 训练神经网络是一个很复杂的过程,在前面提到了深度学习中常用的激活函数,例如ELU或者Relu的变体能够在开始训练的时候很大程度上减少梯度消失或者爆炸问题.但是却不能保证在训练过程中不出现该问题, ...

  3. python实现快速排序

    最近在公司的工作内容发生变化,短期内工作量变少了,这也让我有时间整理一些日常学习和工作中的收获或思路.所以申请了博客,并打算持续更新. 快速排序采用了分治的思想,基本思想是选取数组中一个数为基准数(一 ...

  4. HDU1372搜索

    Knight Moves Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tot ...

  5. Runtime之NSCoding的自动归档、接档

    为什么要有Runtime的NSCoding的自动归档.接档 大家所熟知的方法 //归档方法 - (void)encodeWithCoder:(NSCoder *)aCoder { //当学生被归档,学 ...

  6. 算法-java代码实现快速排序

    快速排序 对于一个int数组,请编写一个快速排序算法,对数组元素排序. 给定一个int数组A及数组的大小n,请返回排序后的数组. 测试样例: [1,2,3,5,2,3],6 [1,2,2,3,3,5] ...

  7. EF+MVC学习中的不理解的问题

    1.之所以被定义为virtual便于实现延迟加载 代码: public virtual ICollection<Enrollment> Enrollments { get; set; } ...

  8. 谈谈Python、Java与AI

    Python好像天生是为AI而生的,随着AI的火热,特别是用Python写的TensorFlow越来越火,Python的热度越来越高,就像当年Java就是随着互联网火起来的感觉.在我的工作中,Pyth ...

  9. Java 通过Xml导出Excel文件,Java Excel 导出工具类,Java导出Excel工具类

    Java 通过Xml导出Excel文件,Java Excel 导出工具类,Java导出Excel工具类 ============================== ©Copyright 蕃薯耀 20 ...

  10. Sublime Text 2激活、插件包安装、以及快捷键

    http://jingyan.baidu.com/article/ff4116259b057c12e48237b8.html Sublime Text作为一款轻量.简洁.高效.跨平台的编辑器.支持N多 ...