python - Python 中响应全局对象的异常

标签 python exception tornado

我是 Python 新手,偶然发现了异常处理的问题。我正在编写一个简单的 Tornado + momoko 应用程序。 总之,我有一个在主函数中创建的全局(?)对象,该对象属于 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 block 中嵌入 queryExec.save() 不起作用。显然我可以将附加参数(引用?)传递给 queryExec.save(),或者向 QueryExecutor 类本身添加某种状态参数,但我想知道是否有更优雅的方法来解决这个问题? p>

编辑: 经过一些修改:

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

最佳答案

save() 不会引发异常;它启动对 _run 的调用,但不会等待它,因此除了记录之外,异常无处可去。要解决此问题,您应该遵循三个规则:

  • 除非您有特定原因使用 @gen.engine,否则应该使用 @gen.coroutine,这会让事情的工作方式更像普通函数。
  • 任何调用协程的方法也必须是协程。该规则也有异常(exception),但它们很微妙,在您更好地处理异步编程之前,您应该遵循它。由于只有协程可以调用协程,因此您只能在某些位置启动链 - 通常是 Tornado 文档中描述为“可能返回 Future”的方法(包括 RequestHandler get/post/etc 方法)<
  • 对协程的调用通常应加上“yield”前缀以等待其结果。如果您在调用协程时不使用“yield”,则应该保存其返回值(一个 Future,它是其实际结果的占位符)并稍后生成它(您可能想要这样做可以并行启动多个协程并同时等待它们)。

所以在这种情况下,制作save()_run()post()协程,并在调用时使用yield关键字_run()save()

关于python - Python 中响应全局对象的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21556658/

相关文章:

python - 如何使用Buildout实现App版本切换?

python - 重新路由 Django 的 "handle_uncaught_exception"

c# - "Exception thrown: ' System.Threading.ThreadAbortException ' in mscorlib.dll"使用 Response.Redirect() 时

python - ggplot2 不存在于 python 的 rpy2 中?

python - 如何在数据集中找到没有分类列和数值列

java - JavaFX-应用程序中的异常

python - 如何在数据库中使 Tornado 请求原子化

python - Tornado websocket 处理程序,self.close() 正在关闭连接而不触发 on_close() 方法

Python Tornado : Sending websocket messages from another class

python - 切片运算符的负边界