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.
Advertisement
Answer
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).