2012-05-07 53 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',所以列表是适当的。 –

相关问题