2012-05-07 52 views
2

在Python中,如何在try/except語句中兩次使用except具有相同異常名稱的塊兩次,而無需將代碼包成多個try/except塊?「except」語句與參數兩次具有相同的異常類

簡單的例子(這裏每個通話pages.get可能引發異常):

try: 
    page = pages.get(lang=lang) 
except Page.DoesNotExist: 
    if not lang == default_lang: 
     page = pages.get(lang=default_lang) 
    else: 
     raise Page.DoesNotExist 
except Page.DoesNotExist: 
    page = pages[0] 

現在,在我的Django應用程序我處理這樣的(但我不想「額外」 try阻止這裏):

try: 
    try: 
     page = pages.get(lang=lang) 
    except Page.DoesNotExist: 
     if not lang == default_lang: 
      page = pages.get(lang=default_lang) 
     else: 
      raise Page.DoesNotExist 
except Page.DoesNotExist: 
    page = pages[0] 

任何處理代碼優於上述表示讚賞! :)

謝謝。

+1

爲什麼要這麼做? – spinlok

+2

你不能。也許你可以告訴我們爲什麼你認爲你需要這樣做,所以我們可以告訴你爲什麼你不需要這樣做 –

+0

我同意,我不認爲這是一個好主意。這意味着你有兩個由同一個事物觸發的代碼路徑,做不同的事情。將try/catch看作if/else語句。 –

回答

1

你不能做到這一點無論與預期elif執行:

if foo == bar: 
    # do "if" 
elif foo == bar: 
    # do "elif" 

而且也沒有理由這樣做,真的。關注你的except

這是你的第一個代碼段的拆解Python的字節碼:

13   0 SETUP_EXCEPT   10 (to 13) 

14   3 LOAD_GLOBAL    0 (NameError) 
       6 RAISE_VARARGS   1 
       9 POP_BLOCK   
      10 JUMP_FORWARD   44 (to 57) 

15  >> 13 DUP_TOP    
      14 LOAD_GLOBAL    0 (NameError) 
      17 COMPARE_OP    10 (exception match) 
      20 POP_JUMP_IF_FALSE  35 
      23 POP_TOP    
      24 POP_TOP    
      25 POP_TOP    

16   26 LOAD_GLOBAL    0 (NameError) 
      29 RAISE_VARARGS   1 
      32 JUMP_FORWARD   22 (to 57) 

17  >> 35 DUP_TOP    
      36 LOAD_GLOBAL    0 (NameError) 
      39 COMPARE_OP    10 (exception match) 
      42 POP_JUMP_IF_FALSE  56 
      45 POP_TOP    
      46 POP_TOP    
      47 POP_TOP    

18   48 LOAD_CONST    1 (1) 
      51 PRINT_ITEM   
      52 PRINT_NEWLINE  
      53 JUMP_FORWARD    1 (to 57) 
     >> 56 END_FINALLY   
     >> 57 LOAD_CONST    0 (None) 
      60 RETURN_VALUE   

很明顯,第一COMPARE_OPNameError(偏移量17)將捕獲的異常和第二個這樣的比較後跳轉到(偏移量36)。

0

在Python或任何Sane語言中的例外都不會按照您打算的方式工作。每次引發異常時,都應追溯堆棧/範圍。在當前範圍內引發的任何異常只能在每個堆棧/範圍內處理一次。 認爲這是每個範圍都有一個單一的異常處理機制,具有一個過濾功能,它只是按照提及的匹配順序過濾異常。如果發生匹配,則按照指定的異常處理程序進行處理。如果任何異常被重新拋出或生成,它應該由下一個異常處理機制處理,該異常處理機制恰好直接進入下一個作用域。

展望的例子,我想知道爲什麼你想通過提高另一個異常,而是不處理它else塊

try: 
    page = pages.get(lang=lang) 
except Page.DoesNotExist: 
    if not lang == default_lang: 
     page = pages.get(lang=default_lang) 
    else: 
     page = pages[0] 
0

雖然這樣的事實複雜,我目前無法弄清楚爲您的使用情況有更好的方式,Python的try/except語句有一些額外的功能:在except塊中引發

try: 
    pass 
    # run your code 
except: 
    pass 
    # run your error handling, etc.. 
else: 
    pass 
    # is run whenever an exception didn't happen 
finally: 
    pass 
    # will be executed always (good for cleaning up) 
0

異常是不是由同一try/except集團處理k,所以你的例子不能工作。即使你能做到,你的榜樣實際上也會產生一個無限循環,因爲第一個except NameError只會再次捕捉到自身內部的異常,並再次提升NameError,等等永遠。

此功能是由設計,因爲否則將不可能編寫異常處理程序,檢查異常但向外引發異常。 except塊僅處理try塊中拋出的異常。如果要處理從except塊中拋出的異常,該塊需要位於try塊內。

1

我建議你創建一個函數來獲取你的頁面,例如。像這樣:

def get_page(language): 
    if language == default_lang: 
     lang_list = [language] 
    else: 
     lang_list = [language, default_lang] 

    for lang in lang_list: 
     try: 
      return pages.get(lang=lang) 
     except Page.DoesNotExist: 
      pass 

    return pages[0] 
+1

@neoascetic你可以只在'set(language,default_lang)'中代替lang,而不是前四行。你還應該將'pages'傳遞給函數。 – detly

+2

@detly集合是無序的,最後應該嘗試'default_lang',所以列表是適當的。 –

相關問題