簡體   English   中英

處理異常的上下文管理器

[英]Context Manager that handles exceptions

我試圖圍繞如何編寫一個上下文管理器來處理在處理任何異常的同時編寫一些日志。 我試圖解決的問題是編寫這樣的代碼:

try:
    # code that can raise exception here
except Exception as e:
    print('failed', e)

print('all good')

這是我在代碼中的重復模式,我認為最好使用上下文管理器處理,例如:

with my_ctx_manager(success_msg='all good', failed_msg='failed):
    # code that can raise exception here

這看起來好多了,但我不知道如何編寫實際的上下文管理器來處理可能在上下文中出現的任何異常。

@contextlib.contextmanager
def my_ctx_manager(success_msg, failed_msg):
   try:
       # if no exception then print(success_msg)
       # How do I catch any exception here
   except Exception:
      print(failed_msg)
      # I need the exception to propagate as well
      raise

我想我的問題更多是這樣的:如何確保上下文管理器正確捕獲、記錄並重新引發正在包裝的代碼的任何異常?

@contextmanager裝飾器的工作方式是,您應該在上下文管理器函數中編寫一次yield ,以便在yield語句暫停函數執行時執行with塊。 這意味着如果with塊拋出異常,您可以通過將yield包裝在try / except塊中來捕獲它:

from contextlib import contextmanager

@contextmanager
def example():
    print('entered the context manager')
    managed_resource = 'some resource'
    try:
        yield managed_resource
    except Exception as e:
        print('caught:', e)
        # any cleanup that should only be done on failure
        raise
    else:
        # any cleanup that should only be done on success
        print('no exception was thrown')
    finally:
        # any cleanup that should always be done
        print('exited the context manager')

with example() as resource:
    print('resource:', resource)
    raise ValueError('some error message')

輸出:

entered the context manager
resource: some resource
caught: some error message
exited the context manager
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
ValueError: some error message

如果您想捕獲所有內容(不僅僅是Exception ),那么您可以編寫一個裸的except:塊並使用sys.exc_info()獲取異常信息。

而不是使用contextmanager ,我覺得這個任務有點笨拙(你需要偽造一個帶有 yield 的生成器來記錄異常),而是自己編寫一個上下文管理器。 它只是一個具有兩個特殊方法的類。 使用預定義的AbstractContextManager您只需要實現其中之一:

import contextlib

class ExceptionLogger(contextlib.AbstractContextManager):

    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type:
            print("***Logging exception {}***".format((exc_type, exc_value, 
                traceback)))

with ExceptionLogger():
    raise ValueError("foo")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM