Một chút điều trị trang trí (lấy cảm hứng rất lỏng lẻo từ Có thể đơn nguyên và nâng). Bạn có thể xóa chú thích loại Python 3.6 một cách an toàn và sử dụng kiểu định dạng thư cũ hơn.
fallible.py
from functools import wraps
from typing import Callable, TypeVar, Optional
import logging
A = TypeVar('A')
def fallible(*exceptions, logger=None) \
-> Callable[[Callable[..., A]], Callable[..., Optional[A]]]:
"""
:param exceptions: a list of exceptions to catch
:param logger: pass a custom logger; None means the default logger,
False disables logging altogether.
"""
def fwrap(f: Callable[..., A]) -> Callable[..., Optional[A]]:
@wraps(f)
def wrapped(*args, **kwargs):
try:
return f(*args, **kwargs)
except exceptions:
message = f'called {f} with *args={args} and **kwargs={kwargs}'
if logger:
logger.exception(message)
if logger is None:
logging.exception(message)
return None
return wrapped
return fwrap
Bản giới thiệu:
In [1] from fallible import fallible
In [2]: @fallible(ArithmeticError)
...: def div(a, b):
...: return a / b
...:
...:
In [3]: div(1, 2)
Out[3]: 0.5
In [4]: res = div(1, 0)
ERROR:root:called <function div at 0x10d3c6ae8> with *args=(1, 0) and **kwargs={}
Traceback (most recent call last):
File "/Users/user/fallible.py", line 17, in wrapped
return f(*args, **kwargs)
File "<ipython-input-17-e056bd886b5c>", line 3, in div
return a / b
In [5]: repr(res)
'None'
Bạn cũng có thể thay đổi giải pháp này để trả lại một cái gì đó có ý nghĩa hơn một chút so với None
từ các except
phần (hoặc thậm chí làm cho giải pháp chung chung, bằng cách xác định giá trị trả về này trong fallible
đối số 's).
exception
phương pháp đơn giản là gọierror(message, exc_info=1)
. Ngay khi bạn chuyểnexc_info
sang bất kỳ phương thức ghi nhật ký nào từ ngữ cảnh ngoại lệ, bạn sẽ nhận được một dấu vết.