In Python, how to make sure database connection will always close before leaving a code block? In Python, how to make sure database connection will always close before leaving a code block? python python

In Python, how to make sure database connection will always close before leaving a code block?


The traditional approach is the try/finally statement:

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)

Since Python 2.6 (and 2.5 with a from __future__ import with_statement), there is an alternative (although try/finally still works perfectly well!): the with statement.

with somecontext as whatever:   # the work goes here

A context has an __enter__ method, executed on entry (to return the whatever above, if you want) and an __exit__ method, executed on exit. Despite the elegance, since there is no existing context that works the way you want, the work needed to build one (although reduced in 2.6 with contextlib) should probably suggest that good old try/finally is best.

If you have 2.6 and want to try contextlib, this is one way you could do it to "hide" the try/finally...:

import contextlib@contextlib.contextmanagerdef dbconnect(**kwds):  dbConnection = MySQLdb.connect(**kwds)  try:    yield dbConnection  finally:    closeDb(dbConnection)

to be used as:

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_

It may be worth it if you are going to use this many, many times, just to avoid repeating the try/finally over and over for each of those many uses.


If MySQLdb supports it, then you could use the "with" statement. The "with" statement exists for just that reason. However, it requires that the object define __enter__ and __exit__ for that to work.

As an example of the with statement... for reading/writing files, you might have:

with open('filename','r') as file:    for line in file:        # processing....# File automatically closed afterwards or if there was an exception thrown

If it doesn't support it, then you can always use try...finally as in:

try:    # Do some processingfinally:    # Cleanup

The finally clause is executed no matter how the try finishes (whether it completed successfull, or an exception was propagated but caught, or an exception was thrown and will continue to propagate).


Why not just wrap it in a try: finally: block?

http://docs.python.org/tutorial/errors.html#defining-clean-up-actions

This is what finally blocks are for.