wim*_*wim 40 python logging exception-handling flow-control try-finally
一旦你进入finally条款,是否有可能判断是否有异常?就像是:
try:
funky code
finally:
if ???:
print('the funky code raised')
Run Code Online (Sandbox Code Playgroud)
我想要做更像这样的事情干:
try:
funky code
except HandleThis:
# handle it
raised = True
except DontHandleThis:
raised = True
raise
else:
raised = False
finally:
logger.info('funky code raised %s', raised)
Run Code Online (Sandbox Code Playgroud)
我不喜欢它需要捕获一个你不打算处理的异常,只是为了设置一个标志.
由于一些评论要求MCVE中的"M"较少,因此这里有一些关于用例的更多背景知识.实际问题是关于日志记录级别的升级.
logger.exception在except块中使用在此处没有帮助.因此,代码在日志捕获上下文(设置自定义处理程序以拦截日志记录)下运行,并且一些调试信息会被追溯重新记录:
try:
with LogCapture() as log:
funky_code() # <-- third party badness
finally:
mylog = mylogger.WARNING if <there was exception> else mylogger.DEBUG
for record in log.captured:
mylog(record.msg, record.args)
Run Code Online (Sandbox Code Playgroud)
MSe*_*ert 40
您可以使用自定义上下文管理器,例如:
class DidWeRaise:
__slots__ = ('exception_happened', ) # instances will take less memory
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
# If no exception happened the `exc_type` is None
self.exception_happened = exc_type is not None
Run Code Online (Sandbox Code Playgroud)
然后在里面使用try:
try:
with DidWeRaise() as error_state:
# funky code
finally:
if error_state.exception_happened:
print('the funky code raised')
Run Code Online (Sandbox Code Playgroud)
它仍然是一个额外的变量,但如果你想在多个地方使用它,它可能更容易重用.而且你不需要自己切换它.
如果您不想要上下文管理器,我会反转触发器的逻辑并仅在没有发生异常的情况下切换它.这样,您就不需要一个except您不想处理的异常案例.最合适的地方else是在try没有抛出异常的情况下输入的子句:
exception_happened = True
try:
# funky code
except HandleThis:
# handle this kind of exception
else:
exception_happened = False
finally:
if exception_happened:
print('the funky code raised')
Run Code Online (Sandbox Code Playgroud)
正如已经指出的那样,您可以使用所需的日志记录功能替换它(在本例中),而不是使用"切换"变量:
mylog = mylogger.WARNING
try:
with LogCapture() as log:
funky_code()
except HandleThis:
# handle this kind of exception
else:
# In case absolutely no exception was thrown in the try we can log on debug level
mylog = mylogger.DEBUG
finally:
for record in log.captured:
mylog(record.msg, record.args)
Run Code Online (Sandbox Code Playgroud)
当然,如果你把它放在你的最后try(如这里建议的其他答案),它也会有用,但我更喜欢这个else条款,因为它有更多含义("只有在try块中没有异常时才会执行该代码")从长远来看可能更容易维护.虽然它比上下文管理器更需要维护,因为变量在不同的地方设置和切换.
sys.exc_info(仅适用于未处理的异常)我想提到的最后一种方法可能对你没用,但对于那些只想知道是否存在未处理的异常(未在任何except块中捕获或已在块内引发的异常)的未来读者可能有用except.在这种情况下,您可以使用sys.exc_info:
import sys
try:
# funky code
except HandleThis:
pass
finally:
if sys.exc_info()[0] is not None:
# only entered if there's an *unhandled* exception, e.g. NOT a HandleThis exception
print('funky code raised')
Run Code Online (Sandbox Code Playgroud)
Jea*_*one 31
raised = True
try:
funky code
raised = False
except HandleThis:
# handle it
finally:
logger.info('funky code raised %s', raised)
Run Code Online (Sandbox Code Playgroud)
鉴于在选择日志级别的问题中添加了额外的背景信息,这似乎很容易适应预期的用例:
mylog = WARNING
try:
funky code
mylog = DEBUG
except HandleThis:
# handle it
finally:
mylog(...)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5090 次 |
| 最近记录: |