在Python中,如何在except
语句中两次使用具有相同异常名称的try/except
块,而无需将代码再包装到另一个try/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]
任何比上述更好的处理代码表示赞赏! :)
感谢。
答案 0 :(得分: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_OP
到NameError
(在偏移17处)将捕获异常并跳转到第二个这样的比较之后(在偏移量36处)。
答案 1 :(得分: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]
答案 2 :(得分: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]
答案 3 :(得分:0)
虽然,我目前无法为您的用例找到更好的方法,但Python的try/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)
答案 4 :(得分:0)
except
块中引发的异常不会由同一try
/ except
块处理,因此您的示例无效。即使你可以,你的例子实际上会产生一个无限循环,因为第一个except NameError
只会再次捕获从内部引发的异常,并再次引发NameError
,依此类推。 / p>
此功能是设计使然,因为否则无法编写检查异常但随后向外引发异常的异常处理程序。 except
块仅处理从try
块中抛出的异常。如果要处理从except
块中抛出的异常,则该块需要位于try
块内。