我正在我的应用程序中使用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会更容易。但我想了解我如何解决这类问题,不仅仅是与数据库有关。
感谢您的建议!
编辑:This post基本上回答了我的问题。
答案 0 :(得分: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" )
这使您能够在一个地方更改数据库或数据库服务器技术。
答案 1 :(得分:2)
请注意,自Python2.6起,sqlite.connect
returns a context manager:
连接对象可以自动用作上下文管理器 提交或回滚事务。如果发生例外,则 交易回滚;否则,交易已经提交:
因此,不会用contextlib.closing
来装饰连接 - 否则,您将失去提交/回滚行为,而只是在退出{时只调用connection.close()
{1}}。
每PEP249:
with-statement
因此,提交/回滚行为比简单地调用close更有用。
您可以使用context manager:
... 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)
,它们只有SQL和参数不同,您可以通过定义getPrice
函数来减少重复的样板代码。
您还可以定义一个上下文管理器,以便在出现错误和提交时回滚连接,并在退出with块时关闭。可以找到一个这样的例子(对于MySQL)here,使它适应sqlite3应该不难......
参考:
答案 2 :(得分:1)
将该逻辑封装到对象中,将该对象传递给数据访问对象并要求它调用方法。
方面或装饰者可能是一种很好的做事方式。
您没有提到合并或交易。想想那些。