首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >响应Python中全局对象的异常

响应Python中全局对象的异常
EN

Stack Overflow用户
提问于 2014-02-04 15:35:23
回答 1查看 395关注 0票数 0

我是Python新手,我偶然发现了一个异常处理问题。我正在编写一个简单的龙卷风+ momoko应用程序。总之,我有一个全局(?)对象是在主函数中创建的,该对象属于QueryExecutor类。它是一个使用momoko处理SQL查询执行的简单类。

代码语言:javascript
复制
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)

我想要实现的是在请求处理程序中使用这个类的对象,并在某种程度上能够判断何时发生了异常:

代码语言:javascript
复制
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和not块中嵌入queryExec.save()不起作用。显然,我可能可以传递额外的参数(引用?)对于queryExec.save(),或者向QueryExecutor类本身添加某种状态参数,但是我想知道是否有更好的方法来解决这个问题?

编辑:修改后:

代码语言:javascript
复制
class TestEx(Exception): pass

以及:

代码语言:javascript
复制
@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")

以及:

代码语言:javascript
复制
try:
    queryExec.save("users", userdata)
except dbsetup.TestEx as ex:
    print("exception caught in caller function")
    self.redirect("templates/login.html")

我进了控制台:

代码语言:javascript
复制
/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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-02-05 00:53:20

save()不会引发异常;它会启动对_run的调用,但不会等待它,因此除了记录异常之外,没有什么地方可以让异常发生。要解决这个问题,您应该遵循三条规则:

  • 除非您有特定的理由使用@gen.engine,否则应该使用@gen.coroutine,这使事情更像正常的函数。
  • 任何调用协同线的方法都必须是协同线。这个规则有异常,但它们很微妙,除非您对异步编程有了更好的处理,否则您应该遵循它。因为只有coroutine可以调用coroutine,所以只能在特定位置启动链--通常在龙卷风文档中被描述为“可能返回未来”的方法(包括RequestHandler get/post/etc方法)。
  • 对协同线的调用通常应该以“收益率”作为前缀,以等待其结果。如果在调用coroutine时不使用“Future”,则应该保存它的返回值( Future,它是其实际结果的占位符),并在以后生成它(您可能希望这样做,并行启动几个coroutine,并同时等待它们)。

因此,在本例中,创建save()_run()post()协同,并在调用_run()save()时使用_run()关键字。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21556658

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档