一个块中有多个尝试代码


75

我在try块中的代码有问题。为了简单起见,这是我的代码:

try:
    code a
    code b #if b fails, it should ignore, and go to c.
    code c #if c fails, go to d
    code d
except:
    pass

这样的事情可能吗?


1
要明确,你要code c被执行,只有当代码B将引发异常
彼得斯

所有代码都应在一个try块中运行,即使它们引发异常。
arvidurs 2013年

2
你不能那样做。没有try块可以抑制所有已执行代码的异常。它可以让您在发生异常时捕获异常,但是该块的其余部分永远不会执行。
马丁·彼得斯

好的,很高兴知道。因此,按代码尝试块
arvidurs 2013年

Answers:


117

您必须制作以下单独的 try块:

try:
    code a
except ExplicitException:
    pass

try:
    code b
except ExplicitException:
    try:
        code c
    except ExplicitException:
        try:
            code d
        except ExplicitException:
            pass

这是假设你想运行code c 如果code b失败。

如果您code c 无论如何都要运行,则需要try一个接一个地放置这些块:

try:
    code a
except ExplicitException:
    pass

try:
    code b
except ExplicitException:
    pass

try:
    code c
except ExplicitException:
    pass

try:
    code d
except ExplicitException:
    pass

我在except ExplicitException这里使用是因为盲目地忽略所有异常永远不是一个好习惯。你会被忽略MemoryErrorKeyboardInterrupt并且SystemExit还有否则,你通常不希望忽略或没有某种形式再次加注或意识理性处理这些拦截。


4
Python的异常处理非常丑陋,它使您编写了为C样式宏哭泣的代码。
Elazar 2013年

13
@Elazar:当您的代码开始看起来像上面的代码时,您真的想重新考虑您在做什么。使用上下文管理器和一些重构,可以使大多数异常处理代码更具可读性和可维护性。
马丁·彼得斯

1
问题是,是否应该仅因为它是python就重新考虑它,所以我必须同时使用异常和缩进。四个简单的操作,每个操作仅在最后一个失败时才执行,并且您会获得4个缩进级别。嗯 如果例外是好的,则应在语法上鼓励使用它们。
Elazar 2013年

重构很好,但是它还带来了诸如绑定和作用域之类的其他问题。
Elazar 2013年

3
OP中没有足够的细节来探讨可能的替代方法。
马丁·彼得

23

您可以使用fuckit模块。
将代码包装在带有@fuckit装饰器的函数中:

@fuckit
def func():
    code a
    code b #if b fails, it should ignore, and go to c.
    code c #if c fails, go to d
    code d

2
这会尝试一次还是在第一个成功运行后停止?
奥斯汀

7
为什么有人会使用这个?
jfleach

9

提取(重构)您的陈述。和使用魔法andor何时决定短路。

def a():
    try: # a code
    except: pass # or raise
    else: return True

def b():
    try: # b code
    except: pass # or raise
    else: return True

def c():
    try: # c code
    except: pass # or raise
    else: return True

def d():
    try: # d code
    except: pass # or raise
    else: return True

def main():   
    try:
        a() and b() or c() or d()
    except:
        pass

3
我认为装饰工会适合这里。
Elazar 2013年

如果b失败(引发异常),c不会执行,也不会执行d
马丁·彼得斯

它已被注释,它只是作为注释而已。...也可以写pass.....对其进行编辑,更好吗?
Inbar Rose

1
好的,这就是我的想法,对于每个代码,我都必须创建一个新的try块。因为假设我有几个代码要运行,所以即使发生异常它也应该继续执行。因为现在做的是,当第一个异常发生时,当B失败时,它将跳过其他代码。这不是我想要的。即使B失败,它也应尝试C,如果C失败,则应尝试D。无论是否出错,它都应贯穿所有行。希望现在更好地理解。
arvidurs 2013年

1
except: pass ... else: return True是一种含蓄的含蓄说法except: return None ... else: return True。最好明确一点。
smci

5

如果您不想链接(大量)try-except子句,则可以循环尝试代码,并在第一次成功时中断。

可以放入函数中的代码示例:

for code in (
    lambda: a / b,
    lambda: a / (b + 1),
    lambda: a / (b + 2),
    ):
    try: print(code())
    except Exception as ev: continue
    break
else:
    print("it failed: %s" % ev)

直接在当前作用域中使用任意代码(语句)的示例:

for i in 2, 1, 0:
    try:
        if   i == 2: print(a / b)
        elif i == 1: print(a / (b + 1))
        elif i == 0: print(a / (b + 2))
        break        
    except Exception as ev:
        if i:
            continue
        print("it failed: %s" % ev)

3

假设每个代码都是一个函数,并且已经编写了代码,然后可以使用以下代码遍历您的编码列表,并在使用“ break”执行函数而没有错误时退出for循环。

def a(): code a
def b(): code b
def c(): code c
def d(): code d

for func in [a, b, c, d]:  # change list order to change execution order.
   try:
       func()
       break
   except Exception as err:
       print (err)
       continue

我在这里使用了“ Exception”,因此您可以看到打印的任何错误。如果您知道期望什么并且不在乎,请关闭打印(例如,如果代码返回两个或三个列表项(i,j = msg.split('。'))。


将thiem作为功能列表(已调用)将立即在列表本身中执行它们,甚至没有达到try
Yesh

1

您可以尝试for循环


for func,args,kwargs in zip([a,b,c,d], 
                            [args_a,args_b,args_c,args_d],
                            [kw_a,kw_b,kw_c,kw_d]):
    try:
       func(*args, **kwargs)
       break
    except:
       pass

这样,您可以循环任意数量的函数,而不会使代码看起来丑陋

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.