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):
JavaScript
x
10
10
1
try:
2
page = pages.get(lang=lang)
3
except Page.DoesNotExist:
4
if not lang == default_lang:
5
page = pages.get(lang=default_lang)
6
else:
7
raise Page.DoesNotExist
8
except Page.DoesNotExist:
9
page = pages[0]
10
For now, in my Django app I do handling like this (but I don’t want “extra” try
block here):
JavaScript
1
11
11
1
try:
2
try:
3
page = pages.get(lang=lang)
4
except Page.DoesNotExist:
5
if not lang == default_lang:
6
page = pages.get(lang=default_lang)
7
else:
8
raise Page.DoesNotExist
9
except Page.DoesNotExist:
10
page = pages[0]
11
Any handling code better than above is appreciated! :)
Thanks.
Advertisement
Answer
You can’t do this either and expect the elif
to execute:
JavaScript
1
5
1
if foo == bar:
2
# do "if"
3
elif foo == bar:
4
# do "elif"
5
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:
JavaScript
1
35
35
1
13 0 SETUP_EXCEPT 10 (to 13)
2
3
14 3 LOAD_GLOBAL 0 (NameError)
4
6 RAISE_VARARGS 1
5
9 POP_BLOCK
6
10 JUMP_FORWARD 44 (to 57)
7
8
15 >> 13 DUP_TOP
9
14 LOAD_GLOBAL 0 (NameError)
10
17 COMPARE_OP 10 (exception match)
11
20 POP_JUMP_IF_FALSE 35
12
23 POP_TOP
13
24 POP_TOP
14
25 POP_TOP
15
16
16 26 LOAD_GLOBAL 0 (NameError)
17
29 RAISE_VARARGS 1
18
32 JUMP_FORWARD 22 (to 57)
19
20
17 >> 35 DUP_TOP
21
36 LOAD_GLOBAL 0 (NameError)
22
39 COMPARE_OP 10 (exception match)
23
42 POP_JUMP_IF_FALSE 56
24
45 POP_TOP
25
46 POP_TOP
26
47 POP_TOP
27
28
18 48 LOAD_CONST 1 (1)
29
51 PRINT_ITEM
30
52 PRINT_NEWLINE
31
53 JUMP_FORWARD 1 (to 57)
32
>> 56 END_FINALLY
33
>> 57 LOAD_CONST 0 (None)
34
60 RETURN_VALUE
35
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).