自动打开和关闭数据库连接

0 投票
3 回答
3332 浏览
提问于 2025-04-17 08:59

我正在为我的应用程序编写一个用于数据库查询的类,使用的是SQLite3。这个类的大部分方法都很相似,像这样:

def getPrice(self, symbol, date):
    date = dt.datetime.strptime(date, '%Y-%m-%d')
    conn = sqlite3.connect('stocks.db')
    curs =conn.cursor()
    curs.execute('''SELECT close FROM prices WHERE symbol = ? AND date = ?;''', (symbol, date))
    close = curs.fetchall()
    curs.close()
    return close

唯一的区别就是数据库查询的内容和参数的数量。有没有办法把打开和关闭数据库连接的过程简化一下呢?

我知道使用像SQLAlchemy这样的ORM可能会更简单。但我想了解的是,如何一般性地解决这类问题,而不仅仅是针对数据库。

谢谢你的建议!

编辑:这篇帖子基本上回答了我的问题。

3 个回答

1

把这些逻辑封装成一个对象,然后把这个对象传给数据访问对象,让它去调用相应的方法。

使用方面或装饰器可能是个不错的选择。

你没有提到连接池或事务,记得也要考虑这些内容。

2

注意,从Python 2.6开始,sqlite.connect 返回一个上下文管理器

连接对象可以作为上下文管理器使用,这样可以自动处理事务的提交或回滚。如果出现异常,事务会被回滚;如果没有异常,事务会被提交:

所以,不要用contextlib.closing来装饰连接——否则你会失去提交/回滚的功能,退出with语句时只会调用connection.close()

根据PEP249

... closing a connection without committing the changes first will cause
an implicit rollback to be performed.

所以,提交/回滚的功能比单纯调用关闭要有用得多。


你可以使用上下文管理器

import contextlib

def query(sql,args):
    with contextlib.closing(sqlite3.connect('stocks.db')) as conn:
        curs = conn.cursor()
        curs.execute(sql,args))
        close = curs.fetchall()
        return close

def getPrice(self, symbol, date):
    date = dt.datetime.strptime(date, '%Y-%m-%d')
    sql = '''SELECT close FROM prices WHERE symbol = ? AND date = ?'''
    args = (symbol, date)
    return query(sql, args)

由于你有很多像getPrice这样的函数,它们只在SQL和参数上有所不同,你可以通过定义query函数来减少重复的样板代码。

你还可以定义一个上下文管理器,在出现错误时回滚连接,并在退出with块时提交和关闭。关于这个(针对MySQL)的示例可以在这里找到,适配到sqlite3应该不难。

参考:

4

首先,只有一个全局连接会让你开心得多。这样配置的改变只需要在一个地方进行,简单方便。

其次,使用 with 语句和上下文管理器库。

from contextlib import closing
from my_database_module import the_global_connection

def getPrice(
    with closing(the_global_connection.cursor())
        curs.execute('''SELECT close FROM prices WHERE symbol = ? AND date = ?;''', (symbol, date))
        close = curs.fetchall()
    return close

你的数据库模块看起来是这样的:

import sqlite3
the_global_connection = sqlite3.connect( "stocks.db" )

这样你就可以在一个地方轻松地更换数据库或数据库服务器技术。

撰写回答