2017-08-11 65 views
0

我正在使用apscheduler的龍捲風調度器。每當任務被調用時,我都需要記錄它的例外情況。爲了處理異常,我創建了一個裝飾器,它將獲得未來的對象並將採取適當的行動。它工作正常,但它不會記錄未來的回調函數。我在回調中完成了Pdb,並且記錄器實例屬性如預期的那樣,但它根本不記錄文件。 守則,日誌記錄不工作在tornado.concurrent.Future的回調中

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 

附:我正在使用python2.7

回答

1

包裝缺少未來的回報 - 沒有這個,如果會有一些異步調用,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 

如果有任何其他的問題,我相信它的相關記錄配置/設置。

+0

然而,我已經使用'yield'(在調用者中)和'gen.Return'(在被調用者中)一起使用。我可以在'try except'塊中處理異常。它會像正常的「同步」執行一樣好嗎?供參考 - > https://gist.github.com/pranav93/3c34d6cfc2b5d8956625e4cd66bdfa34 – pnv