我有一个用Tornado构建的小型web应用程序,我想在其中使用ZODB进行一些数据存储。根据ZODB的文件,multi-threaded programs are supported, but they should start up a new connection per thread。我想这意味着我必须做一些事情,比如
### On startup
dbFilename = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Data.fs")
db = DB(FileStorage(dbFilename))
### Example handler
class Example(tornado.web.RequestHandler):
def get(self):
try:
conn = db.open()
root = conn.root()
### do stuff with root here
root._p_changed = 1 ## Include these lines for writes
transaction.commit() ## on sub-elements
finally:
conn.close()首先,新的连接对于所有与数据库交互的处理程序还是只对执行写入的处理程序都是必需的?在启动时启动一个连接并在我所有的阅读中使用它,然后只在我需要写一些东西的时候才执行上面的连接,这是合理的吗?
其次,在Python中抽象该模式的惯用方式是什么?我有一些类似这样的东西
def withDB(fn):
try:
conn = db.open()
root = conn.root()
res = fn(root)
root._p_changed = 1
transaction.commit()
return res
finally:
conn.close()
def delete(formName):
def local(root):
### do stuff with root here
return withDB(local)但这可能是我的Lisp演示。
也欢迎对该方法进行全面的头部检查。
发布于 2013-04-10 03:56:57
您需要为每个线程创建一个新连接。ZODB为每个连接提供了一致的每个事务视图(MVCC,多视图并发控制),因此即使对于读取,您也需要一个单独的连接。该连接可以重用于一个线程中的顺序请求。
因此,对于连接,我将使用ZODB.DB提供的每线程池,可能会缓存每个请求的连接(如pyramid_zodbconn所做的)。
在请求处理程序中,您可以使用事务管理器作为上下文管理器:
class Example(tornado.web.RequestHandler):
def get(self):
connection = some_connection_pool.get_connection()
with transaction.manager:
root = conn.root()
res = fn(root)
root._p_changed = 1使用transaction.manager对象作为上下文管理器可以确保事务在enter时启动,在exit时无异常提交,在exit出现异常时中止。
您还可以创建一个上下文管理器来处理ZODB连接:
from contextlib import contextmanager
@contextmanager
def zodbconn(db):
conn = db.open()
yield conn.root()
conn.close()然后将其与事务管理器一起用作上下文管理器:
class Example(tornado.web.RequestHandler):
def get(self):
with zodbconn(db) as root, transaction.manager:
res = fn(root)
root._p_changed = 1此上下文管理器获取数据库对象,并返回根对象,在再次退出上下文时自动关闭连接。
https://stackoverflow.com/questions/15911121
复制相似问题