我对Python中的装饰器有一个奇怪的问题。基本上我正在尝试包装一个函数,因此它会根据每个请求创建和拆除游标(不要问 - 这只是一个对于演示问题有用的示例!我还有其他目的而不仅仅是这个)
以下是一个示例:
class DB(object):
"""Our DB methods and connections"""
def __init__(self):
self.con = oursql.connect(host=host, user=user, passwd=passwd,
port=port, db=db)
self.cursor = None
def __del__(self):
self.con.close()
def wrapper(func):
"""Wrapper for our database methods"""
def _exec(*args):
"""Wherein the wrapping takes place"""
db.cursor = db.con.cursor()
func(*args)
db.cursor.close()
return _exec
@wrapper
def get_tables(db):
"""Returns a list of all tables in the database"""
results = []
db.cursor.execute('show tables')
tables = db.cursor.fetchall()
for table in tables:
results.append(table[0])
print results
return results
if __name__ == '__main__':
db = DB()
print get_tables(db)
这样可行,但我得到的结果只包含函数中的None:
[list of tables from "print results" goes in here]
None <- returned by the "print get_tables(db)" line
答案 0 :(得分:3)
您忽略了包装函数的返回值:
db.cursor = db.con.cursor()
func(*args)
db.cursor.close()
这里你的函数没有明确的返回值,因此Python为你提供了默认值None
。
您想要捕获返回值并返回:
db.cursor = db.con.cursor()
retval = func(*args)
db.cursor.close()
return retval
您可以在此处使用try:
/ finally
来确保即使引发异常也会关闭游标;这也简化了代码,因为finally
套件总是被执行,即使在try
块中返回时也是如此:
db.cursor = db.con.cursor()
try:
return func(*args)
finally:
db.cursor.close()
另一种选择是将光标用作上下文管理器;在这种情况下,任何交易也将自动为您承诺;在一个例外情况下,该事务将被回滚。在任何一种情况下,当上下文退出时,光标将也关闭:
with db.con.cursor() as db.cursor:
return func(*args)
请参阅我们的自己的文档中的cursors as context managers。