使用mypy时在python中正确键入异常/错误的元组

问题描述 投票:1回答:1

我已经编写了自己的装饰器add_warning,以便在发生某些错误时打印costom错误消息。装饰器接受一条消息以及要为其打印此消息的错误类型。我还想向此装饰器添加类型,并使用mypy检查它。这在我使用Exception时仅抛出普通Type[Exception]的情况下效果很好。但是,当我使用诸如mypyOSError之类的其他错误时,AttributeError抱怨说:

error: Argument "errors" to "add_warning" has incompatible type "Tuple[Type[OSError], Type[AttributeError]]"; expected "Union[str, Type[Exception], Tuple[Type[Any]]]"

有人知道在这里使用AnyTuple[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()
python exception typing mypy
1个回答
0
投票

问题是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()
© www.soinside.com 2019 - 2024. All rights reserved.