【问题标题】:Handling multiple exceptions in functions [closed]处理函数中的多个异常[关闭]
【发布时间】:2019-04-14 11:42:57
【问题描述】:

我有一个使用http.server 用Python 3 编写的小型网络服务器,它在方法do_GET() 中调用函数translate(),如下所示:

class httpd(BaseHTTPRequestHandler):
    def do_GET(self):
        self.wfile.write(bytes(f'{translate(var[0])}', 'utf-8'))

现在在这个translate() 函数中,我有几个条件语句和tryexcept 块大致如下:

def translate(param):
    try:
        # do something
    except SomeError as some_err:
        print("Error: " % some_err)
        return ""

    if True:
        try:
            # do something
        except SomeOtherError as some_other_err:
            print("Error: " % some_other_err)
            return ""
        except SomeThirdError as some_third_err:
            print("Third error: " % some_third_err)
            return ""
    else:
        # additional try and except blocks which print an error and
        # return an empty string

上面的代码被简化了,但原则上如果发生异常,我会返回一个空字符串,因此如果发生异常,我的 Web 服务器不会向客户端返回任何内容。

有没有更易于管理的方法来处理这个问题?具体来说,我希望:

  • 避免通过单独的except 部分捕获每个错误,同时仍支持取决于错误类型的错误消息。
  • 避免在我的函数中编写多个 try / except 语句,这些语句通常是嵌套的。

注意:这是this now deleted question 的副本。该帖子中的解决方案包含在下面,但欢迎提供其他答案。

【问题讨论】:

  • 这是一个非常广泛的问题。异常处理非常特定于所涉及的用例,如果重组,您的实际应用程序很可能完全避免一堆异常。但是对于过于通用的Something..Error 异常和do something 代码,我们只能给出非常广泛的建议。上下文管理器可以提供帮助,但不是通用的万能解决方案。捕获基本异常是另一回事。使用except (Exc1, Exc2, Exc3) 然后在异常处理程序中从那里分派是第三个。这些都有不同的特点。
  • 但是写下所有这些需要接近可出版书籍状态的东西,所以我已经关闭了它,因为太宽泛了。

标签: python python-3.x exception error-handling exception-handling


【解决方案1】:

我不确定在您的逻辑中嵌套try 块是否绝对必要,但我会尝试使用自定义Exception 类的单个try 块。像这样的:

class MyException(Exception):
    """Generic error message."""
    def __str__(self):
        return self.__doc__

class SomeError(MyException):
    """SomeError message."""
    pass

class SomeOtherError(MyException):
    """SomeOtherError message."""
    pass

class SomeThirdError(MyException):
    """SomeThirdError message."""
    pass



def translate(param):
    try:
        # do something
        ...
        if cond1:
            raise SomeError()
        ...
        if cond2:
            raise SomeOtherError()
        ...
        if cond3:
            raise SomeThirdError()
        ...

    except MyException as err:
        print(err)
        return ""

【讨论】:

  • @jpp 如果您引发任何子类异常,您将输出正确的消息,因为您在基类的__str__ 方法中有return self.__doc__,这就是子类和继承的工作方式。为了清楚起见,我已经更新了示例。
【解决方案2】:

如何定义一个包含所有错误和响应的字典的函数。在这种情况下,您可以一次捕获异常并将其发送给处理程序

更新:

def handle (e) :

exp = {'IOError' : 'NO such a file in dir ...! ' ,
       'KeyboardInterrupt' : 'Exiting ... (Keyboard interruption)',
       'IndexError' : ' a sequence subscript is out of range' ,
       'NameError' : 'a local or global name is not found'}

for key , value in exp.items() :
    if e == key :
        print (value) #or do whatever you want

def test() :
    try :
        f = open('no-file' , 'r')
    except Exception as e :
        handle (type(e).__name__)


if __name__ == "__main__" :
    test()

【讨论】:

  • 可能不言而喻,但 ... 位在这里是相关的,如果您可以用用户可以运行的简单示例填写它们会很有帮助。
  • 你是对的,我希望这会有所帮助。
【解决方案3】:

contextmanager 怎么样?为了减轻您对自定义错误消息的担忧,您可以提供一个字典,将错误类映射到您选择的消息。

由于不同的操作需要处理不同的错误,您可以使用多个with 语句,每次将不同的错误作为参数提供。

这是一个人为的例子:

from contextlib import contextmanager

@contextmanager
def error_handling(msg, *exceptions):
    try:
        yield
    except exceptions as my_error:
        print(msg[my_error.__class__], my_error)
        return ''

def do_stuff(d, key, index):

    custom_msg = {IndexError: 'You have an Index Error!',
                  KeyError: 'You have a Key Error!'}

    with error_handling(custom_msg, IndexError, KeyError):
        return d[key][index]

# example prints "You have an Index Error! list index out of range"; then returns ''
do_stuff({'a': [0, 1, 2]}, 'a', 10)

【讨论】:

    猜你喜欢
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-29
    • 2011-02-07
    相关资源
    最近更新 更多