In Python, how can I use except
block with same exception name twice in try/except
statements without need to wrap code into one more try/except
block?
Simple example (here each call of pages.get
may raise the exception):
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]
For now, in my Django app I do handling like this (but I don't want "extra" try
block here):
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]
Any handling code better than above is appreciated! :)
Thanks.
You can't do this either and expect the elif
to execute:
if foo == bar:
# do "if"
elif foo == bar:
# do "elif"
And there's no reason to do this, really. Same for your except
concern.
Here's the disassembled Python bytecode of your first code snippet:
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
It's obvious that the first COMPARE_OP
to NameError
(at offset 17) will catch the exception and jump to after the second such comparison (at offset 36).