cre*_*gox 18 python database-connection nested
我想尽可能地防止数据库连接被打开,因为这个代码将在密集使用的服务器上运行,这里的人已经告诉我应该尽快关闭数据库连接.
def do_something_that_needs_database ():
dbConnection = MySQLdb.connect(host=args['database_host'], user=args['database_user'], passwd=args['database_pass'], db=args['database_tabl'], cursorclass=MySQLdb.cursors.DictCursor)
dbCursor = dbConnection.cursor()
dbCursor.execute('SELECT COUNT(*) total FROM table')
row = dbCursor.fetchone()
if row['total'] == 0:
print 'error: table have no records'
dbCursor.execute('UPDATE table SET field="%s"', whatever_value)
return None
print 'table is ok'
dbCursor.execute('UPDATE table SET field="%s"', another_value)
# a lot more of workflow done here
dbConnection.close()
# even more stuff would come below
Run Code Online (Sandbox Code Playgroud)
我相信当桌子上没有行时会打开数据库连接,所以我仍然不确定它是如何工作的.
无论如何,也许这是糟糕的设计,因为我可以在每个小块之后打开和关闭数据库连接execute
.当然,我可以在这种情况下添加一个close
权利return
......
但是,我怎么能总是正确关闭数据库,而不必担心,如果我有return
,或raise
,或continue
,或任何中间?我正在考虑像代码块一样的东西,类似于使用try
,就像在下面的建议中一样,这显然不起作用:
def do_something_that_needs_database ():
dbConnection = MySQLdb.connect(host=args['database_host'], user=args['database_user'], passwd=args['database_pass'], db=args['database_tabl'], cursorclass=MySQLdb.cursors.DictCursor)
try:
dbCursor = dbConnection.cursor()
dbCursor.execute('SELECT COUNT(*) total FROM table')
row = dbCursor.fetchone()
if row['total'] == 0:
print 'error: table have no records'
dbCursor.execute('UPDATE table SET field="%s"', whatever_value)
return None
print 'table is ok'
dbCursor.execute('UPDATE table SET field="%s"', another_value)
# again, that same lot of line codes done here
except ExitingCodeBlock:
closeDb(dbConnection)
# still, that "even more stuff" from before would come below
Run Code Online (Sandbox Code Playgroud)
我不认为有什么类似ExitingCodeBlock
的例外,我知道有尝试 else
,但我希望Python已经有类似的功能......
或者也许有人可以建议我采取范式,并告诉我这很糟糕,并高度建议我永远不要这样做.也许这只是不用担心的事情,让MySQLdb处理它,或者是它?
Ale*_*lli 25
传统方法是try
/ finally
声明:
def do_something_that_needs_database ():
dbConnection = MySQLdb.connect(host=args['database_host'], user=args['database_user'], passwd=args['database_pass'], db=args['database_tabl'], cursorclass=MySQLdb.cursors.DictCursor)
try:
# as much work as you want, including return, raising exceptions, _whatever_
finally:
closeDb(dbConnection)
Run Code Online (Sandbox Code Playgroud)
从Python 2.6(和2.5 with a from __future__ import with_statement
)开始,有一个替代方案(尽管try
/ finally
仍然可以很好地工作!):with
声明.
with somecontext as whatever:
# the work goes here
Run Code Online (Sandbox Code Playgroud)
上下文有一个__enter__
方法,在入口处执行(whatever
如果需要,返回上面的内容)和一个__exit__
在退出时执行的方法.尽管优雅,但由于没有现有的上下文按照你想要的方式工作,所以构建一个所需的工作(虽然减少了2.6 contextlib
)应该可能表明好的旧尝试/最终是最好的.
如果您有2.6并想尝试contextlib
,这是一种可以"隐藏"try/finally ...的方法:
import contextlib
@contextlib.contextmanager
def dbconnect(**kwds):
dbConnection = MySQLdb.connect(**kwds)
try:
yield dbConnection
finally:
closeDb(dbConnection)
Run Code Online (Sandbox Code Playgroud)
用作:
def do_something_that_needs_database ():
with dbconnect(host=args['database_host'], user=args['database_user'],
passwd=args['database_pass'], db=args['database_tabl'],
cursorclass=MySQLdb.cursors.DictCursor) as dbConnection:
# as much work as you want, including return, raising exceptions, _whatever_
Run Code Online (Sandbox Code Playgroud)
如果你要使用这么多次,可能是值得的,只是为了避免重复尝试/最后反复使用这些中的每一个.
如果MySQLdb支持它,那么你可以使用" with "语句.出于这个原因,存在"with"语句.但是,它要求对象定义__enter__和__exit__以使其起作用.
作为with语句的示例...用于读取/写入文件,您可能具有:
with open('filename','r') as file:
for line in file:
# processing....
# File automatically closed afterwards or if there was an exception thrown
Run Code Online (Sandbox Code Playgroud)
如果它不支持它,那么你总是可以使用try ... finally,如:
try:
# Do some processing
finally:
# Cleanup
Run Code Online (Sandbox Code Playgroud)
无论try如何完成(无论是成功完成,还是传播但是被捕获,或者抛出异常并且将继续传播),finally子句都会被执行.
归档时间: |
|
查看次数: |
17808 次 |
最近记录: |