Python - 在“try”之后使用“except”作为“try”的“else”部分

Posted

技术标签:

【中文标题】Python - 在“try”之后使用“except”作为“try”的“else”部分【英文标题】:Python - Using the "except" after "try", as an "else" part for "try" 【发布时间】:2020-08-19 22:25:54 【问题描述】:

我试图了解(但找不到明确的答案),将 try-except 的“except”部分用作“else”部分是否被认为是一种好的做法。

编辑 - 为了尝试更清楚:

假设我有 2 个变量要测试,而我只“需要”其中一个作为答案(例如 if-else)。如果失败,他们每个人都会引发异常。我尝试了第一个,但失败了。使用“except”部分继续使用第二个变量的代码并将其设置为所选变量是一种好习惯,还是我应该只使用“except”部分来处理异常,然后执行一些其他代码(外部“除外”范围)也测试第二个?


原文:

也就是 - 将一些代码写入 except,这不仅仅是一个小的 except 句柄或打印。更像是只有在抛出异常时才会发生的几行代码块,类似于“else”语句。也就是说,与将 except 用作专门处理抛出的异常及其后果的一部分相反。

示例 -

try: perform-this-thing...

     perform-some-code

except:
     exception-raised-so-do-this-code...
     code
     code
     code

如果这不被认为是好的做法 - 做我所寻求的更正确的方法是什么?

谢谢大家。

【问题讨论】:

现在这不是“好”的方式。您应该尝试使用 if 语句。 如果该代码仅在引发异常时才有意义,那么它您的异常处理代码,显然它应该放在那里。 假设我有 2 个变量要测试,而我只“需要”其中一个作为答案(如 if-else)。如果失败,他们每个人都会引发异常。我尝试了第一个,但失败了。使用“except”部分继续使用第二个变量的代码并将其设置为所选变量是一种好习惯,还是我应该只使用“except”部分来处理异常,然后执行一些其他代码(外部“除外”范围)也测试第二个? @OronW 你能用那个例子更新你的问题吗?会更容易理解你的意思。 当然。我已经编辑了我的问题。希望它会让它更清楚 【参考方案1】:

异常处理是对破坏正常程序执行流程的编程错误作出响应的过程。这里的重点应该是“扰乱正常流程”。

使用异常处理程序从此类编程错误中恢复,但不掩盖真正的编程错误。使用通配符异常处理程序时尤其要小心,并极其谨慎地使用它。

我认为测试两个变量并继续其中一个变量(如果已设置)是正常的业务逻辑,应该包含在 if-else 语句中,因为这是您的正常流程。

如果您只能通过异常测试来执行此测试,那么我会说您可以将单个变量测试包装在 try-except 中,如果不可避免,请使用嵌套异常处理,但我建议不要嵌套异常处理,因为它使代码丑陋且不可维护(嵌套将在这里测试第一个变量的except 中的第二个变量)。

如果没有设置它们会导致异常,因为这会破坏正常流程。

try:
    # Try to obtain variable 1
except ErrorObtainingVariable1
    # Log...
try:
    # Try to obtain variable 2
except ErrorObtainingVariable2
    # Log...
# Check to use variable 1 or 2
# If none set raise exception

(PS: try-except 还有一个可选的 else 部分,它跟在所有 except 子句之后,如果没有引发异常则执行。如果获得第一个变量成功。有关详细信息,请参阅the Python documentation。)

【讨论】:

感谢您的回答。如果我理解正确 - 你建议只使用 except 来管理异常。使用您的方法,我必须管理 2 个不同的变量,然后 always 测试它们 both 以查看哪个没有引发异常,并将其用作我的结果。对于“如果第一个引发异常 - 使用另一个”这样的“简单”测试,这感觉有点长。我错过了什么吗?还是这只是更正确的方法,即使它更长一点?再次感谢 一般规则应该是避免将过多的业务逻辑放入异常处理程序中,正确。但是 Python 确实提供了带有异常处理的控制流机制,并且在您的用例中这就是您想要做的。因此,请尽量避免将其用作else,除非在特殊用例中。绝对避免使用广泛的except。我个人不觉得上述解决方案很长,它可能很冗长但它是可维护的。如果您正在寻找更优雅的东西,我认为@Gabip 解决方案很棒(除了广泛的except)。【参考方案2】:

我更愿意使用以下方法来防止缩进地狱

# create an auxiliary function to choose the valid variable
def choose_variable(*vars):
    default_value = -1 # you can change it or remove it if you the default return value is None
    for v in vars:
        try:
            # check your var here
            return v
        except:
            continue
    return default_value

然后在你的代码中使用它:

chosen_value = choose_variable(v1,v2,v3)
print(f"The chosen value is chosen_value")

【讨论】:

这是一个很棒的实现! (在我看来)。由于这并不能真正回答我对该线程的一般性问题,因此我不能选择它作为答案,因为我正在寻找更通用的代码编写实践。但是,我想我一定会将此表格用作我的武器库的一部分 我认为您的问题是这是否是一个好习惯,我回答说 IMO,这不是,因为缩进地狱会导致您的代码可读性降低。我误解你的问题了吗? 我的问题是关于在良好编码方面的单一尝试例外的正确做法。作为我的第一句话,我试图理解 - 使用“except”部分运行一些仅在异常情况下运行的代码是否被认为是一种好习惯(或者我应该在异常范围之外运行它)。我认为我的示例可能有点令人困惑,因此我对其进行了编辑,但问题不涉及缩进或多个/嵌套的 try-except。但是,我再次认为您的方法非常优雅,如果没有其他通用解决方案建议,我会选择它。再次感谢! @OronW 您问在except 套件中“运行仅在异常情况下运行的代码”是否是一种好习惯。嗯,根据定义应该是这样。它还能放在什么地方?无论如何,我鼓励你用一个具体的例子来更新你的问题,因为我的印象是人们在猜测你的要求,因此没有提供准确的答案。它将帮助您获得适合您特定问题的答案。 我知道我的描述可能与预期不同,但我试图尽可能笼统。关键是要了解我应该在except中放入什么类型的内容 - 只处理异常本身(写入日志文件,打印到屏幕等)然后做更多的代码逻辑,或者我可以/应该在里面写更多的逻辑除了。我觉得@yvesonline 回答了我的问题,所以我选择了那个答案。我也认为 Gabip 的实现非常好,我将来肯定会使用它。非常感谢大家花时间在这里回答【参考方案3】:

在我看来,如果用例非常简单的话,try-except 块的这两种使用形式是完全一样的。像这样的:

try:

    var1 = var + 1
    print(var1)

except:

    print(var)

    try:

        var1 = var + float(1)
        print(var1)

    except:

        print(var)

print('\n')

这个版本相当于第一个版本的try-except块

try:
    var1 = var + 1
    print(var1)

except:

    print(var)


try:

    var1 = var + float(1)
    print(var1)

except:

    print(var)

print('\n')

但根据您要达到的效果,代码可能看起来不同,并产生不同的结果。像这样:

try:
    var1 = var + '1'
    print(var1)

except:

    print(var)


try:

    var1 = var + float(1)
    print(var1)

except:

    print(var)

print('\n')

第三个版本的结果与第二个版本不同。

另一种编写代码的方法是这样,这是简化的。


try:
    var1 = var + '1'
    print(var1)

except:

    try:

        var1 = var + float(1)
        print(var1)

    except:

        print(var)

而且这个版本和第一个版本的try-except块不一样。

当代码执行时,会有不同的结果。

15
15


15
15


151
15


151

Try-except 块可能会变得非常复杂,您必须为您的特定用例选择最佳版本。

【讨论】:

感谢您的回答。我试图避免嵌套的 try-except,如果我将使用非嵌套版本,那么即使第一次尝试成功 - 它也会在第二次尝试时被覆盖(假设它也成功)。我的目标是测试第一个并尽可能使用它。只有第一个失败时,我才会测试第二个。 是的,我同意。 Try-except 结构通常需要很多关注。我很高兴我的回答有所帮助! 我同意第一个版本是最容易使用的,但是第一个 try-except 块不能覆盖第二个 try-except 块。无论如何,这确实很复杂,如您所见。我的意思是,非嵌套版本似乎更易于使用。

以上是关于Python - 在“try”之后使用“except”作为“try”的“else”部分的主要内容,如果未能解决你的问题,请参考以下文章

Python3 错误处理

python中的 try...except...finally 的用法

python 异常

第八篇 Python异常

Python - 在“try”之后使用“except”作为“try”的“else”部分

python中用来抛出异常的关键字是