2013-10-22 75 views
21

發生異常後,可以返回執行try-block嗎? (我們的目標是少寫) 例如:python捕獲異常,並繼續嘗試塊

try: 
    do_smth1() 
except: 
    pass 

try: 
    do_smth2() 
except: 
    pass 

VS

try: 
    do_smth1() 
    do_smth2() 
except: 
    ??? # magic word to proceed to do_smth2() if there was exception in do_smth1 
+0

不能返回到'try'塊一旦中斷,沒有。 –

+0

我覺得沒有。某些結構必須對流進行分段,並指定下一個要執行的點(此代碼段中的「do_smth2」)。的 – Jokester

+3

可能重複[A Python的方式爲「恢復下一個」例外?](http://stackoverflow.com/questions/18655481/a-pythonic-way-for-resume-next-on-exceptions) –

回答

27

不,你不能這樣做。這就是Python的語法。一旦你因爲例外而退出一個try-block,就沒有辦法回來了。

雖然for循環呢?

funcs = do_smth1, do_smth2 

for func in funcs: 
    try: 
     func() 
    except Exception: 
     pass # or you could use 'continue' 

但請注意,裸露的except被認爲是不好的做法。你應該趕上一個特定的例外。我捕獲了Exception,因爲如果不知道這些方法可能拋出什麼異常,我就可以做到這一點。

+0

最起碼捕獲異常。這捕獲最異常,但忽略了SystemExit和一個KeyboardInterrupt你幾乎從來沒有想除了可能趕在你的程序的頂層。 – Evan

4

你可以通過你的方法重複...

for m in [do_smth1, do_smth2]: 
    try: 
     m() 
    except: 
     pass 
1

我不認爲你想這樣做。一般情況下使用try聲明的正確方法儘可能精確。我認爲這將是更好的事情可做:

try: 
    do_smth1() 
except Stmnh1Exception: 
    # handle Stmnh1Exception 

try: 
    do_smth2() 
except Stmnh2Exception: 
    # handle Stmnh2Exception 
1

根據您需要的位置和頻率要做到這一點,你也可以編寫一個函數,它會爲你:

def live_dangerously(fn, *args, **kw): 
    try: 
     return fn(*args, **kw) 
    except Exception: 
     pass 

live_dangerously(do_smth1) 
live_dangerously(do_smth2) 

但在其他答案已經注意到,有一個空值except通常表示你的代碼有其他錯誤。

5

你可以實現你想要的,但使用不同的語法。 try/except後可以使用「finally」塊。這樣做,無論拋出異常,python都會執行代碼塊。

像這樣:

try: 
    do_smth1() 
except: 
    pass 
finally: 
    do_smth2() 

但是,如果你想要執行do_smth2()只如果沒有拋出的異常,請使用 「其他」 塊:

try: 
    do_smth1() 
except: 
    pass 
else: 
    do_smth2() 

你可以將它們混合在try/except/else/finally子句中也是如此。 玩得開心!

3

你可以處理這種情況的一種方法是使用發電機。不要調用函數,而要調用它;那麼無論在消費發生器可以發送主叫它放回發生器,或定點的結果,如果發電機失敗:那上面完成蹦牀看起來可能是這樣:

def consume_exceptions(gen): 
    action = next(gen) 
    while True: 
     try: 
      result = action() 
     except Exception: 
      # if the action fails, send a sentinel 
      result = None 

     try: 
      action = gen.send(result) 
     except StopIteration: 
      # if the generator is all used up, result is the return value. 
      return result 

發電機,將是兼容這個應該是這樣的:

def do_smth1(): 
    1/0 

def do_smth2(): 
    print "YAY" 

def do_many_things(): 
    a = yield do_smth1 
    b = yield do_smth2 
    yield "Done" 
>>> consume_exceptions(do_many_things()) 
YAY 

注意do_many_things()通話do_smth*,它只是得到他們,consume_exceptions叫他們代其

12

而其他的答案和接受的一個是正確的,應該遵循在真正的代碼,只是爲了保持完整性和幽默,你可以嘗試fuckitpyhttps://github.com/ajalt/fuckitpy)模塊。

您的代碼可以更改爲以下幾點:

@fuckitpy 
def myfunc(): 
    do_smth1() 
    do_smth2() 

然後調用myfunc()會打電話do_smth2()即使在do_smth1())

注意一個例外:請不要嘗試在任何真正的代碼,這是褻瀆

+0

這是一個理想的黑客,儘管如你所說,絕對不會被真正的代碼釋放,唯一的缺點是(我沒有設法解決),它不能訪問全局變量,不像'try/except'方法,或者'with fuckit:'('fuckit'裝飾者似乎比'fuckit:'更有用)。 – oliversm

0

special_func以避免嘗試 - 除了重複:

def special_func(test_case_dict): 
    final_dict = {} 
    exception_dict = {} 

    def try_except_avoider(test_case_dict): 

     try: 
      for k,v in test_case_dict.items(): 
       final_dict[k]=eval(v) #If no exception evaluate the function and add it to final_dict 

     except Exception as e: 
      exception_dict[k]=e #extract exception 
      test_case_dict.pop(k) 
      try_except_avoider(test_case_dict) #recursive function to handle remaining functions 

     finally: #cleanup 
      final_dict.update(exception_dict) 
      return final_dict #combine exception dict and final dict 

    return try_except_avoider(test_case_dict) 

運行代碼:

def add(a,b): 
    return (a+b) 
def sub(a,b): 
    return (a-b) 
def mul(a,b): 
    return (a*b) 

case = {"AddFunc":"add(8,8)","SubFunc":"sub(p,5)","MulFunc":"mul(9,6)"} 
solution = special_func(case) 

輸出的樣子:

{'AddFunc': 16, 'MulFunc': 54, 'SubFunc': NameError("name 'p' is not defined")} 

要轉換爲變量:

locals().update(solution) 

變量會是什麼樣子:

AddFunc = 16, MulFunc = 54, SubFunc = NameError("name 'p' is not defined")