patternpythonMinor
Simple decorator for creating and managing a database cursor
Viewed 0 times
simplemanagingcreatingdatabaseforanddecoratorcursor
Problem
I'm working on a simple decorator that creates and manages a database cursor. The goal is to 'inject' the cursor as the first argument of the function, but not expose it to the caller.
Usage:
Decorator:
Is this a good approach?
Usage:
import psycopg2
@needsNewCursor
def findItem(cursor, item_id):
cursor.execute('SELECT name FROM items WHERE id = %s', [item_id])
item_result = cursor.fetchone()
# ...
return item
# caller only needs to know about the ID
findItem(1234)Decorator:
def needsNewCursor(func):
def decorator(*args, **kargs):
print 'Creating new cursor'
# This is slightly different in the final code, but I'm only
# concerned about how I'm dealing with decorators, at the moment
cursor = createDefaultCursor()
if cursor:
with cursor:
# Pass the cursor in as the 1st param
return func(cursor, *args, **kargs)
# Give the function a chance to deal with fails
return func(None, *args, **kargs)
# QUESTION: Is this enough?
decorator.__name__ = func.__name__
return decoratorIs this a good approach?
Solution
No, I don't think this is a good approach. Anyone who sees the declaration
You could just as well have
Even better might be to create a context manager to deal with opening and closing a cursor and start each function with a statement like
Anyway, when writing decorators, instead of assigning yourself
One more thing: in your example
def findItem(cursor, item_id): will call the function with two arguments and scratch one's head to no end when it does not work.You could just as well have
cursor = createDefaultCursor() as the first line of each function that uses a cursor. The number of lines does not increase as you can omit the @needsNewCursor line.Even better might be to create a context manager to deal with opening and closing a cursor and start each function with a statement like
with new_cursor() as cursor:. A context manager also has an opportunity to deal with exceptions raised in the with block.Anyway, when writing decorators, instead of assigning yourself
decorator.__name__ = func.__name__ you can apply the functools.wraps decorator that also copies the docstring.One more thing: in your example
needsNewCursor is a decorator. You should choose a different name for the inner function.Context
StackExchange Code Review Q#33678, answer score: 5
Revisions (0)
No revisions yet.