【问题标题】:Python shorthand exception handlingPython 速记异常处理
【发布时间】:2016-11-03 17:49:08
【问题描述】:

我在 Python 中处理异常时遇到了一些问题。在许多情况下,我希望忽略所有异常的代码区域。假设我有 100 行代码希望发生这种情况。

这是大多数人认为的解决方案:

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

这实际上不适用于我的情况(以及许多其他情况)。假设第 3 行有一个异常。一旦抛出异常,它直接“通过”,并跳过第 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

但是,很明显,这非常丑陋、草率,而且绝对需要永远。如何以更短、更简洁的方式完成上述代码?如果您提供允许将“通过”替换为其他代码的方法,则会获得奖励积分。

【问题讨论】:

  • 听起来您需要对代码进行一些认真的重新设计。你真的有 100 行完全独立的代码,它们完全不相互依赖,不能放在一个循环中,所有代码都可能以你的代码可以从中恢复的方式失败吗?
  • 如果你在做测试,你真的应该有增量测试......所以例如......如果工作流程是a->b->c,做c,它需要先做 a->b.... 所以如果 a 或 b 失败,就没有理由测试 c。
  • 我实际上没有 100 行,但有时我有 6 或 7 行。哪怕只有6、7个,还是很草率的。
  • 是的,在好的代码中,您应该只捕获您期望的异常,这意味着您应该确定要捕获的异常。以您的错误代码可以工作的方式捕获异常将是一个非常非常糟糕的主意。抓东西,例如将字符串转换为整数,但字符串无法转换,因为它不代表数字。
  • 但是,这些真的是完全独立的吗?比如,如果其中任何一个失败了,你的程序就完全没问题了吗?你不能把它们放在一个循环中吗?

标签: python python-2.7 exception


【解决方案1】:

正如其他答案已经说明的那样,您应该考虑重构您的代码。

也就是说,我无法抗拒不将某些东西组合在一起以便能够执行您的功能而不会失败并在发生异常时中断。

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 行),因为这是生产代码。我的整个代码并没有像这样草率,但是有些地方事情变得超级复杂和混乱。
【解决方案2】:

您可以尝试将代码分成更小的块,以便它可以正确处理错误,而不是需要放弃所有进度并循环返回。

除此之外可以使用的另一种解决方案是进行检查,如果为您的代码设置标志以检查它是否可以继续,或者是否需要重复最后一步,您将能够防止额外的迭代。

例子:

while not continue:
    try:
        a = input('Enter data')
    except:
        pass
    if a != null:
        continue = true

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    • 1970-01-01
    • 2016-02-11
    • 2011-10-09
    • 2017-04-05
    相关资源
    最近更新 更多