Python简写异常处理

3

我在 Python 异常处理方面遇到了一个问题。存在一种情况,我希望忽略某些代码区域中的所有异常。比如说,我有 100 行代码需要这样做。

大多数人可能会认为以下是解决方法:

try:
    line 1
    line 2
    line 3
    ...
    line 99
    line 100
except:
    pass

在我的情况(以及许多其他情况)下,这实际上是不起作用的。假设第三行有一个异常。一旦抛出异常,它就直接跳到“pass”,并跳过第4-100行。我能想到的唯一解决方案是这样的:

try:
    line 1
except:
    pass

try:
    line 2
except:
    pass

try:
    line 3
except:
    pass

...

try:
    line 99
except:
    pass

try:
    line 100
except:
    pass

但是,显而易见的是,这种方法非常丑陋、杂乱无章,并且非常耗时。有什么更短、更简洁的方法可以完成上述代码?如果您提供一种允许“pass”被替换为其他代码的方法,将会得到额外的加分。


7
听起来你需要认真重新设计你的代码。你是否真的有100个完全独立、彼此不依赖且不能放在循环中的代码行,这些代码行都可能以你的代码无法恢复的方式失败? - Morgan Thrapp
如果你正在进行测试,无论如何都应该有增量测试... 例如... 如果工作流程是a->b->c,要做c,它需要先做a->b.... 所以如果a或b失败,就没有必要测试c。 - Fallenreaper
1
是的,在良好的代码中,您应该只捕获某种程度上预期的异常,这意味着您肯定应该指定要捕获的异常。以一种使您的糟糕代码能够工作的方式捕获异常是非常非常糟糕的想法。例如,捕获将字符串转换为整数但无法转换的情况,因为该字符串不表示数字。 - Falk Schuetzenmeister
但是,再次强调,它们真的完全独立吗?也就是说,如果它们中的任何一个失败了,你的程序就完全没问题了吗?而且你不能把它们放在循环中吗? - Morgan Thrapp
嗯,有时它们也是独立的。在许多情况下,我需要这样做。 - Douglas
显示剩余3条评论
2个回答

4

正如其他答案所述,您应该考虑重构您的代码。

话虽如此,我还是忍不住想要拼凑一些东西,以便能够执行您的函数而不会失败并在发生异常时退出。

import ast, _ast, compiler

def fail():
    print "Hello, World!"
    raise Exception
    x = [4, 5]
    print x

if __name__ == '__main__':
    with open(__file__, 'r') as source:
        tree = ast.parse(source.read(), __file__)
        for node in ast.iter_child_nodes(tree):
            if isinstance(node, _ast.FunctionDef):
                _locals = {}
                for line in node.body:
                    mod = ast.Module()
                    mod.body = [line]
                    try:
                        exec(compile(mod, filename='<ast>', mode='exec'), _locals, globals())
                    except:
                        import traceback
                        traceback.print_exc()

这段代码会执行全局范围内发现的任何函数,并防止在出现错误时退出。它通过迭代文件的AST,在每行函数中创建一个新的模块来执行。

如您所料,程序的输出结果为:

Hello, World!
Traceback (most recent call last):
  File "kek.py", line 18, in <module>
    exec(compile(m, filename='<ast>', mode='exec'), _locals, globals())
  File "<ast>", line 3, in <module>
Exception
[4, 5]

我应该强调,在任何生产代码中使用这个都是一个糟糕的想法。但是为了论证,类似这样的东西可以工作。你甚至可以将其包装在一个漂亮的装饰器中,尽管这并不能改变它是一个糟糕的想法的事实。
愉快的重构!

虽然这不是我想要的答案,但它确实回答了我的问题。因为这是生产代码,所以我可能会坚持用旧方法(只有几行代码,而不是100行)。虽然我的整个代码并不像这样邋遢,但有些地方变得非常复杂和混乱。 - Douglas

0
你可以尝试将代码分成较小的块,以便它能够正确处理错误,而不需要放弃所有进度并循环回去。
除此之外,另一个解决方案是进行检查,如果为代码设置标志以检查它是否可以继续执行或者是否需要重复上一步骤,那么您就可以避免额外的迭代。
例如:
while not continue:
    try:
        a = input('Enter data')
    except:
        pass
    if a != null:
        continue = true

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接