我是Python的新手,我偶然发现了异常处理的问题。我正在写一个简单的龙卷风+ momoko应用程序。 总之,我有一个在main函数中创建的全局(?)对象,该对象是QueryExecutor类。这是一个使用momoko处理SQL查询执行的简单类。
class QueryExecutor:
def __init__(self, database):
self.db = database
@gen.engine
def _run(self, query):
self.db.execute(query, callback = (yield gen.Callback('q')))
try:
cursor = yield momoko.WaitOp('q')
except Exception as error:
print(str(error))
def save(self, tablename, data):
fields = "(" + ", ".join(map(str, list(data.keys()))) + ")"
values = "(" + "\'" + '\', \''.join(map(str, list(data.values()))) + "\'" + ")"
query = "INSERT INTO " + tablename + " " + fields + " VALUES " + values + ";"
self._run(query)
我想要实现的是在请求处理程序中使用此类的对象,并以某种方式能够判断何时发生异常:
class RegistrationHandler(tornado.web.RequestHandler):
def get(self):
self.render("templates/register.html")
def post(self):
#...handle post arguments, retrieve user data, check if correct etc., do stuff...
#...if everything ok:
queryExec.save("users", userdata)
#what to do if save threw an exception?
application.db = momoko.Pool(dsn=dbsetup.dsn, size=1)
if __name__ == "__main__":
queryExec = dbsetup.QueryExecutor(database=application.db)
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
queryExec.save()在查询失败时抛出异常,我想在请求处理函数内部知道它是否发生。在try和except块中嵌入queryExec.save()不起作用。显然,我可以将其他参数(引用?)传递给queryExec.save(),或者将某种状态参数添加到QueryExecutor类本身,但我想知道是否有更优雅的方法来解决这个问题?
编辑: 经过一些修改后:
class TestEx(Exception): pass
和
@gen.engine
def _run(self, query):
self.db.execute(query, callback = (yield gen.Callback('q')))
try:
cursor = yield momoko.WaitOp('q')
except Exception as error:
print(str(error))
raise TestEx("test exception")
和
try:
queryExec.save("users", userdata)
except dbsetup.TestEx as ex:
print("exception caught in caller function")
self.redirect("templates/login.html")
我进入控制台:
/usr/bin/python3.3 /home/tybur/PycharmProjects/tornadochat/main.py
duplicate key value violates unique constraint "unique_names"
DETAIL: Key (name)=(testuser) already exists.
ERROR:tornado.application:Exception in callback None
Traceback (most recent call last):
File "/home/tybur/PycharmProjects/tornadochat/dbsetup.py", line 46, in _run
cursor = yield momoko.WaitOp('q')
File "/usr/local/lib/python3.3/dist-packages/tornado/gen.py", line 520, in run
next = self.yield_point.get_result()
File "/usr/local/lib/python3.3/dist-packages/momoko/utils.py", line 59, in get_result
raise error
File "/usr/local/lib/python3.3/dist-packages/momoko/connection.py", line 244, in io_callback
state = self.connection.poll()
psycopg2.IntegrityError: duplicate key value violates unique constraint "unique_names"
DETAIL: Key (name)=(testuser) already exists.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.3/dist-packages/tornado/ioloop.py", line 688, in start
self._handlers[fd](fd, events)
File "/usr/local/lib/python3.3/dist-packages/tornado/stack_context.py", line 331, in wrapped
raise_exc_info(exc)
File "<string>", line 3, in raise_exc_info
File "/usr/local/lib/python3.3/dist-packages/tornado/stack_context.py", line 302, in wrapped
ret = fn(*args, **kwargs)
File "/usr/local/lib/python3.3/dist-packages/momoko/connection.py", line 248, in io_callback
self.callback(error)
File "/usr/local/lib/python3.3/dist-packages/tornado/stack_context.py", line 331, in wrapped
raise_exc_info(exc)
File "<string>", line 3, in raise_exc_info
File "/usr/local/lib/python3.3/dist-packages/tornado/stack_context.py", line 302, in wrapped
ret = fn(*args, **kwargs)
File "/usr/local/lib/python3.3/dist-packages/tornado/gen.py", line 574, in inner
self.set_result(key, result)
File "/usr/local/lib/python3.3/dist-packages/tornado/gen.py", line 500, in set_result
self.run()
File "/usr/local/lib/python3.3/dist-packages/tornado/gen.py", line 529, in run
yielded = self.gen.throw(*exc_info)
File "/home/tybur/PycharmProjects/tornadochat/dbsetup.py", line 49, in _run
raise TestEx("test exception")
dbsetup.TestEx: test exception
答案 0 :(得分:1)
save()
不会引发异常;它开始调用_run
但不等待它,因此除了要记录之外,没有任何地方可以去除异常。要解决此问题,您应遵循以下三条规则:
@gen.engine
,否则您应该使用@gen.coroutine
代替,这会使事情更像普通函数。Future
,这是其实际结果的占位符)并稍后生成(您可能希望这样做并行启动多个协同程序并立即等待它们。)因此,在这种情况下,请设置save()
,_run()
和post()
协同程序,并在调用_run()
和save()
时使用yield关键字。