【问题标题】:Try/Except entire block without breaking flow在不中断流程的情况下尝试/排除整个块
【发布时间】:2020-11-19 17:27:31
【问题描述】:

我有一些这样的代码:

var_1 = something_complicated("Look here")[0].text.split()[0]
var_2 = something_complicated("Look there")[0].text.split()[2:]
var_3 = something_complicated("Look up")[0].text.split()
var_4 = " ".join(something_complicated("Look down"))
var_5 = int(something_complicated("Don't Look here").split()[1])

除了更像 15 个变量。我想写一些会产生这种效果的东西:

try:
    var_1 = something_complicated("Look here")[0].text.split()[0]
    var_2 = something_complicated("Look there")[0].text.split()[2:]
    var_3 = something_complicated("Look up")[0].text.split()
    var_4 = " ".join(something_complicated("Look down"))
    var_5 = int(something_complicated("Don't Look here").split()[1])
except IndexError, TypeError:
    var_that_caused_error = ""

并且程序并没有退出,即使错误发生在 var_1 中,其余变量仍然会被填充

我现在能想到的解决方案是尝试/排除每一行,但这似乎是一场噩梦,而且也不遵循 DRY。有什么建议吗?

【问题讨论】:

  • 您可以编写代码来检查引发这些异常的条件,如果它是重复的,您可以将其分解为一个或多个函数。
  • @DennisSparrow,你能举一个简短的例子来说明你的意思吗?

标签: python-3.x try-except


【解决方案1】:

这是一种方法,尽管可能有更好的方法来解决这个问题。

try:
     something_complicated("Look here")[0].text.split()[0]
     something_complicated("Look there")[0].text.split()[2:]
     something_complicated("Look up")[0].text.split()
     " ".join(something_complicated("Look down"))
     int(something_complicated("Don't Look here").split()[1])
     var1 = something_complicated("Look here")[0].text.split()[0]
     var2 = something_complicated("Look there")[0].text.split()[2:]
     var3 = something_complicated("Look up")[0].text.split()
     var4 = " ".join(something_complicated("Look down"))
     var5 = int(something_complicated("Don't Look here").split()[1])

except:
    var_that_caused_error = ""

【讨论】:

  • 感谢您试一试。程序启动时不是所有的exp都运行吗?他们什么都没做,所以程序仍然可以中断。
  • @Lafftar 是的,你是对的。我修复了程序,我认为这应该可以工作。
  • 好的,所以你运行这些函数而不将返回数据保存到任何东西,5 次,然后将它们返回到一个变量,5 次。如果第二行发生错误,整个程序不会仍然失败吗?另外,这个程序怎么知道是什么 var 导致了错误?
【解决方案2】:

我不确定这是否足以作为答案,但您要求提供示例,并且在 cmets 中发布的代码大小有限且难以阅读,因此我发布此答案是希望它可能是有用。

异常应该会破坏控制流。如果您不希望控制流中断,您可以如您所说,将每个语句放在自己的try 子句中,或者您可以检查错误情况并避免做会引发异常的事情。例如,在尝试使用序列的元素之前,可以检查该元素是否存在。

例子:

#var_1 = something_complicated("Look here")[0].text.split()[0]

var_1 = ""                          #   Default value until we know success
var = something_complicated("Look here")
if len(var) > 0:                    #   Prevent IndexError
    var = var[0]
    if hasattr(var, "text"):        #   Prevent AttributeError
        var = var.text
        if isinstance(var, str):    #   Prevent AttributeError
            var = var.split()
            if len(var) > 0:        #   Prevent IndexError
                var_1 = var[0]      #   Success

我知道这是更多的行。这就是您为控制控制流而付出的代价。您不必检查所有可能的错误情况。你可以跳过检查你有足够信心不会出现的情况,只要你愿意接受一个例外,如果确实出现了。

作为一个函数分解的示例,假设您在示例代码中看到模式[0].text.split() 重复出现。您可以创建一个函数来执行此操作并检查如下错误情况:

def text_words(obj):
    if len(obj) > 0:                    #   Prevent IndexError
        result = obj[0]
        if hasattr(result, "text"):     #   Prevent AttributeError
            result = result.text
            if isinstance(result, str): #   Prevent AttributeError
                return result.split()
    return None
    
words = text_words(something_complicated("Look here"))
var_1 = words[0] if words else ""

【讨论】:

  • 感谢您抽出宝贵时间回答这些 Dennis,非常感谢。我想我明白你在说什么,问题是,正如你所说,这个解决方案不仅仅是尝试/排除每一行。另外,我必须编写不同的 text_words() 因为它们都有不同的转换。这就像增加了 10 倍的努力。无论如何,感谢您花时间写详细的回复,谢谢。
猜你喜欢
  • 2013-05-28
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-14
  • 2015-10-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多