使用 mypy 时在 python 中正确键入 exceptions/errors 的元组
Correct typing of tuple of exceptions/errors in python when using mypy
我已经编写了自己的装饰器 add_warning
以便在发生某些错误时打印自定义错误消息。装饰器接受一条消息和打印该消息的错误类型。我还想为这个装饰器添加类型并使用 mypy
检查它。这在我使用 Type[Exception]
时只是抛出普通 Exception
的情况下效果很好。但是,mypy
在我使用 OSError
或 AttributeError
等其他错误时抱怨说:
error: Argument "errors" to "add_warning" has incompatible type "Tuple[Type[OSError], Type[AttributeError]]"; expected "Union[str, Type[Exception], Tuple[Type[Any]]]"
.
有人知道是否有比在这里使用 Any
或 Tuple[Type[OSError], Type[AttributeError]]
更好的方法吗?具体来说,所有 Python 错误是否有更通用的类型?
下面是代码:
from functools import wraps
from typing import Union, Tuple, Callable, Type
def add_warning(message: str, flag: str = 'Info',
errors: Union[str, Type[Exception], Tuple[Type[Exception]]] = 'all') -> Callable:
"""
Add a warning message to a function, when certain error types occur.
"""
if errors == 'all':
errors = Exception
def decorate(func: Callable):
@wraps(func)
def wrapper(*args, **kwargs):
try:
result = func(*args, **kwargs)
except errors:
warn(message, flag)
return []
else:
return result
return wrapper
return decorate
def warn(message: str, flag: str = 'Info') -> None:
"""Print the colored warning message."""
print(f"{flag}: {message}")
if __name__ == '__main__':
@add_warning('This is another test warning.', flag='Error')
def test_func1():
raise Exception
@add_warning('This is a test warning.', flag='Error', errors=(OSError, AttributeError))
def test_func2():
raise OSError
test_func1()
test_func2()
问题是 Tuple[Type[Exception]
表示具有单个值的元组。你想要一个可变大小的元组,所以使用省略号:Tuple[Type[Exception], ...]
下面的工作没有 mypy 抱怨:
from functools import wraps
from typing import Union, Tuple, Callable, Type
def add_warning(message: str, flag: str = 'Info',
errors: Union[str, Type[Exception], Tuple[Type[Exception], ...]] = 'all') -> Callable:
"""
Add a warning message to a function, when certain error types occur.
"""
if errors == 'all':
errors = Exception
def decorate(func: Callable):
@wraps(func)
def wrapper(*args, **kwargs):
try:
result = func(*args, **kwargs)
except errors:
warn(message, flag)
return []
else:
return result
return wrapper
return decorate
def warn(message: str, flag: str = 'Info') -> None:
"""Print the colored warning message."""
print(f"{flag}: {message}")
if __name__ == '__main__':
@add_warning('This is another test warning.', flag='Error')
def test_func1():
raise Exception
@add_warning('This is a test warning.', flag='Error', errors=(OSError, AttributeError))
def test_func2():
raise OSError
test_func1()
test_func2()
我已经编写了自己的装饰器 add_warning
以便在发生某些错误时打印自定义错误消息。装饰器接受一条消息和打印该消息的错误类型。我还想为这个装饰器添加类型并使用 mypy
检查它。这在我使用 Type[Exception]
时只是抛出普通 Exception
的情况下效果很好。但是,mypy
在我使用 OSError
或 AttributeError
等其他错误时抱怨说:
error: Argument "errors" to "add_warning" has incompatible type "Tuple[Type[OSError], Type[AttributeError]]"; expected "Union[str, Type[Exception], Tuple[Type[Any]]]"
.
有人知道是否有比在这里使用 Any
或 Tuple[Type[OSError], Type[AttributeError]]
更好的方法吗?具体来说,所有 Python 错误是否有更通用的类型?
下面是代码:
from functools import wraps
from typing import Union, Tuple, Callable, Type
def add_warning(message: str, flag: str = 'Info',
errors: Union[str, Type[Exception], Tuple[Type[Exception]]] = 'all') -> Callable:
"""
Add a warning message to a function, when certain error types occur.
"""
if errors == 'all':
errors = Exception
def decorate(func: Callable):
@wraps(func)
def wrapper(*args, **kwargs):
try:
result = func(*args, **kwargs)
except errors:
warn(message, flag)
return []
else:
return result
return wrapper
return decorate
def warn(message: str, flag: str = 'Info') -> None:
"""Print the colored warning message."""
print(f"{flag}: {message}")
if __name__ == '__main__':
@add_warning('This is another test warning.', flag='Error')
def test_func1():
raise Exception
@add_warning('This is a test warning.', flag='Error', errors=(OSError, AttributeError))
def test_func2():
raise OSError
test_func1()
test_func2()
问题是 Tuple[Type[Exception]
表示具有单个值的元组。你想要一个可变大小的元组,所以使用省略号:Tuple[Type[Exception], ...]
下面的工作没有 mypy 抱怨:
from functools import wraps
from typing import Union, Tuple, Callable, Type
def add_warning(message: str, flag: str = 'Info',
errors: Union[str, Type[Exception], Tuple[Type[Exception], ...]] = 'all') -> Callable:
"""
Add a warning message to a function, when certain error types occur.
"""
if errors == 'all':
errors = Exception
def decorate(func: Callable):
@wraps(func)
def wrapper(*args, **kwargs):
try:
result = func(*args, **kwargs)
except errors:
warn(message, flag)
return []
else:
return result
return wrapper
return decorate
def warn(message: str, flag: str = 'Info') -> None:
"""Print the colored warning message."""
print(f"{flag}: {message}")
if __name__ == '__main__':
@add_warning('This is another test warning.', flag='Error')
def test_func1():
raise Exception
@add_warning('This is a test warning.', flag='Error', errors=(OSError, AttributeError))
def test_func2():
raise OSError
test_func1()
test_func2()