在协同程序Python3+;龙卷风4.3+;本机日志记录模块

在协同程序Python3+;龙卷风4.3+;本机日志记录模块,python,logging,format,tornado,Python,Logging,Format,Tornado,在Tornado中,一个异常被封装在一个未来中,异步函数的调用方必须给出未来来解包该异常。如果异步函数调用链较长,如何让日志消息正确打印出函数名和发生异常的行 例如,在下面的代码中: FORMAT = '%(asctime)s - %(levelname)s - %(filename)s : %(lineno)s'\ ' - %(funcName)20s() - %(message)s\n' logging.basicConfig(format=FORMAT) ... @

在Tornado中,一个异常被封装在一个未来中,异步函数的调用方必须给出未来来解包该异常。如果异步函数调用链较长,如何让日志消息正确打印出函数名和发生异常的行

例如,在下面的代码中:

FORMAT = '%(asctime)s - %(levelname)s - %(filename)s : %(lineno)s'\
         ' - %(funcName)20s() - %(message)s\n'

logging.basicConfig(format=FORMAT)

...

@gen.coroutine
def layer_2():
    return(yield async_func())

@gen.coroutine 
def layer_1():
    return(yield layer_2())

@gen.coroutine
def main():
    try:
        yield layer_1()
    except Exception as e:
        logging.warning('Error: {}'.format(str(e))
如果在
async_func()
中引发异常,则日志消息
lineno
funcName
main()
的异常,而不是
async_func()
的异常

除了每个
yield
语句的
try
catch
之外,还有什么解决方案吗?谢谢


编辑1:我意识到我的问题的答案可能与Tornado无关,但我只是将其包括在这里,因为这是我的情况。

我看到您使用的是Python 3,在Python 3中,来自Futures的异常会自动进行回溯。使用
logging.exception
打印它:

@gen.coroutine
def main():
    try:
        yield layer_1()
    except Exception as e:
        logging.exception(e)
日志记录中没有什么神秘的事情发生。您可以自己打印回溯:

@gen.coroutine
def main():
    try:
        yield layer_1()
    except Exception as e:
        import traceback
        traceback.print_exc()
与常规函数调用堆栈的回溯相比,这种回溯有一些额外的内容:对gen.Runner.run的调用,这是Tornado协同程序实现的一部分。但是它有它的作用:您可以看到
main
位于堆栈的顶部,而
async_func
位于堆栈的底部

这在Python3中起作用,因为每个异常都有一个回溯,Tornado在异常处理过程中展开堆栈时,会正确地将协同程序的回溯附加到异常


最后,如果将
gen.coroutine
替换为
async def
,您将获得由Python 3.5解释器本身实现的非常清晰的回溯。

我看到您使用的是Python 3,在Python 3中,来自Futures的异常会自动提供回溯。使用
logging.exception
打印它:

@gen.coroutine
def main():
    try:
        yield layer_1()
    except Exception as e:
        logging.exception(e)
日志记录中没有什么神秘的事情发生。您可以自己打印回溯:

@gen.coroutine
def main():
    try:
        yield layer_1()
    except Exception as e:
        import traceback
        traceback.print_exc()
与常规函数调用堆栈的回溯相比,这种回溯有一些额外的内容:对gen.Runner.run的调用,这是Tornado协同程序实现的一部分。但是它有它的作用:您可以看到
main
位于堆栈的顶部,而
async_func
位于堆栈的底部

这在Python3中起作用,因为每个异常都有一个回溯,Tornado在异常处理过程中展开堆栈时,会正确地将协同程序的回溯附加到异常


最后,如果您将
gen.coroutine
替换为
async def
,您将得到Python 3.5解释器本身实现的非常清晰的回溯。

啊,这非常有用!非常感谢。我想这是你帮我解决的第二个问题!啊,这太有用了!非常感谢。我想这是你帮我解决的第二个问题!