记录在 tornado.concurrent.Future 的回调中不起作用
Logging not working in callback of tornado.concurrent.Future
我正在使用 apscheduler 的 tornado 调度程序。每当调用任务时,我都需要记录它的异常。为了处理异常,我创建了一个装饰器,它将获得未来的对象并采取适当的行动。它工作正常,但它没有记录在未来的回调函数中。我已经在回调内部完成了 Pdb,并且记录器实例属性符合预期,但它仍然根本没有记录文件。
代码是,
logger = logging.getLogger('myLogger')
def handle_callback(result):
logger.debug(result.result())
logger.info(result.result())
logger.error(result.result())
logger.exception(result.result())
logger.exception(result.exc_info())
def handle_exceptions():
def wrapped(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
future = fn(*args, **kwargs)
future.add_done_callback(handle_callback)
return wrapper
return wrapped
@handle_exceptions()
@gen.coroutine
def run_task(job_id):
logger.info('executing job {}'.format(job_id))
raise MyException
P.S。我正在使用 python2.7
包装器缺少未来的 return - 没有这个,如果有一些异步调用,ioloop 将不会继续。让我们添加一些异步调用
@handle_exceptions
@gen.coroutine
def run_task(job_id):
logger.info('executing job {}'.format(job_id))
yield gen.sleep(1)
raise Exception('blah')
您可能已经注意到,我已从装饰器中删除 ()
以简化它。它不必嵌套。所以装饰器看起来像:
def handle_exceptions(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
future = fn(*args, **kwargs)
future.add_done_callback(handle_callback)
return future # <<< we need this
return wrapper
接下来,处理程序的回调正在调用 Future.result()
,这将立即重新引发异常。所以最好先检查一下是否有异常:
def handle_callback(result):
exc_info = result.exc_info()
if exc_info:
logger.error('EXCEPTION %s', exc_info)
将其组合成一个简单的例子:
import logging
from functools import wraps, partial
from tornado import gen, ioloop
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def handle_callback(result):
exc_info = result.exc_info()
if exc_info:
logger.error('EXCEPTION %s', exc_info)
def handle_exceptions(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
future = fn(*args, **kwargs)
future.add_done_callback(handle_callback)
return future
return wrapper
@handle_exceptions
@gen.coroutine
def run_task(job_id):
logger.info('executing job {}'.format(job_id))
yield gen.sleep(1)
raise Exception('blah')
ioloop.IOLoop.instance().run_sync(partial(run_task, 123))
由于问题本身不提供有关日志记录的任何信息,因此我使用了更改级别的标准。
代码输出:
INFO:root:executing job 123
ERROR:root:EXCEPTION (<type 'exceptions.Exception'>, Exception('blah',), <traceback object at 0x7f807df07dd0>)
Traceback (most recent call last):
File "test.py", line 31, in <module>
ioloop.IOLoop.instance().run_sync(partial(run_task, 123))
File "/tmp/so/lib/python2.7/site-packages/tornado/ioloop.py", line 458, in run_sync
return future_cell[0].result()
File "/tmp/so/lib/python2.7/site-packages/tornado/concurrent.py", line 238, in result
raise_exc_info(self._exc_info)
File "/tmp/so/lib/python2.7/site-packages/tornado/gen.py", line 1069, in run
yielded = self.gen.send(value)
File "test.py", line 28, in run_task
raise Exception('blah')
Exception: blah
如果还有任何其他问题,我认为它与日志记录有关 config/setup。
我正在使用 apscheduler 的 tornado 调度程序。每当调用任务时,我都需要记录它的异常。为了处理异常,我创建了一个装饰器,它将获得未来的对象并采取适当的行动。它工作正常,但它没有记录在未来的回调函数中。我已经在回调内部完成了 Pdb,并且记录器实例属性符合预期,但它仍然根本没有记录文件。 代码是,
logger = logging.getLogger('myLogger')
def handle_callback(result):
logger.debug(result.result())
logger.info(result.result())
logger.error(result.result())
logger.exception(result.result())
logger.exception(result.exc_info())
def handle_exceptions():
def wrapped(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
future = fn(*args, **kwargs)
future.add_done_callback(handle_callback)
return wrapper
return wrapped
@handle_exceptions()
@gen.coroutine
def run_task(job_id):
logger.info('executing job {}'.format(job_id))
raise MyException
P.S。我正在使用 python2.7
包装器缺少未来的 return - 没有这个,如果有一些异步调用,ioloop 将不会继续。让我们添加一些异步调用
@handle_exceptions
@gen.coroutine
def run_task(job_id):
logger.info('executing job {}'.format(job_id))
yield gen.sleep(1)
raise Exception('blah')
您可能已经注意到,我已从装饰器中删除 ()
以简化它。它不必嵌套。所以装饰器看起来像:
def handle_exceptions(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
future = fn(*args, **kwargs)
future.add_done_callback(handle_callback)
return future # <<< we need this
return wrapper
接下来,处理程序的回调正在调用 Future.result()
,这将立即重新引发异常。所以最好先检查一下是否有异常:
def handle_callback(result):
exc_info = result.exc_info()
if exc_info:
logger.error('EXCEPTION %s', exc_info)
将其组合成一个简单的例子:
import logging
from functools import wraps, partial
from tornado import gen, ioloop
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def handle_callback(result):
exc_info = result.exc_info()
if exc_info:
logger.error('EXCEPTION %s', exc_info)
def handle_exceptions(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
future = fn(*args, **kwargs)
future.add_done_callback(handle_callback)
return future
return wrapper
@handle_exceptions
@gen.coroutine
def run_task(job_id):
logger.info('executing job {}'.format(job_id))
yield gen.sleep(1)
raise Exception('blah')
ioloop.IOLoop.instance().run_sync(partial(run_task, 123))
由于问题本身不提供有关日志记录的任何信息,因此我使用了更改级别的标准。 代码输出:
INFO:root:executing job 123
ERROR:root:EXCEPTION (<type 'exceptions.Exception'>, Exception('blah',), <traceback object at 0x7f807df07dd0>)
Traceback (most recent call last):
File "test.py", line 31, in <module>
ioloop.IOLoop.instance().run_sync(partial(run_task, 123))
File "/tmp/so/lib/python2.7/site-packages/tornado/ioloop.py", line 458, in run_sync
return future_cell[0].result()
File "/tmp/so/lib/python2.7/site-packages/tornado/concurrent.py", line 238, in result
raise_exc_info(self._exc_info)
File "/tmp/so/lib/python2.7/site-packages/tornado/gen.py", line 1069, in run
yielded = self.gen.send(value)
File "test.py", line 28, in run_task
raise Exception('blah')
Exception: blah
如果还有任何其他问题,我认为它与日志记录有关 config/setup。