看来SQLite从3.7.13开始就支持多线程访问,Python的sqlite3
模块从3.4开始就支持多线程访问。要使用它,可以编写如下代码:
import sqlite3
dburi = "file:TESTING_MEMORY_DB?mode=memory&cache=shared"
connection = sqlite3.connect(dburi, uri=True, check_same_thread=False)
with connection:
cursor = conneciton.cursor()
cursor.execute("SQL")
这是可行的,但是您首先会发现,您需要锁定对数据库的访问,否则另一个线程可能会损坏您的数据。可能是这样的:
^{pr2}$现在,如果一个线程获得锁,另一个线程在第一个线程关闭它之前无法获取它,只要所有线程使用相同的lock
对象,并记住在with connection:
之前with lock:
,那么您的数据就不会被破坏。在
但是,现在我需要一种方法来通过连接传递锁。您可以使用单独的参数来完成此操作,也可以使用自定义类:
import threading
import sqlite3
class LockableSqliteConnection(object):
def __init__(self, dburi):
self.lock = threading.Lock()
self.connection = sqlite3.connect(dburi, uri=True, check_same_thread=False)
dburi = "file:TESTING_MEMORY_DB?mode=memory&cache=shared"
lsc = LockableSqliteConnection(dburi)
with lsc.lock:
with lsc.connection:
cursor = lsc.connection.cursor()
cursor.execute("SQL")
lsc.connection.commit()
这很好,因为类的名称让我想起了我所拥有的,所以至少我不太可能忘记锁并损坏我的数据。但是,有没有办法消除这两个with
语句?理想情况下,我希望将它们组合成一个with
,因为无论如何我都不应该在没有锁的情况下使用连接。在
在本文的帮助下,我能够写出满足我需求的东西:http://effbot.org/zone/python-with-statement.htm
我的代码如下:
此类的对象现在可以直接用于
^{pr2}$with
语句:它还方便地为我打开一个游标,并自动提交我对数据库所做的更改,这意味着调用新类的代码更短。这很好,但是自动提交数据库更改实际上可能不是最好的主意。。。在更复杂的场景中,您可能希望启动一个事务,然后将其回滚到一半,那么这个功能可能会带来麻烦。但是,我的SQL需求非常简单,而且我从不回滚,所以现在我把它留在我的项目中。在
相关问题 更多 >
编程相关推荐