Reputation: 18745
I'm working on a function which can raise
multiple Exceptions
. I want to handle these Exceptions
in their except blocks and then return result with custom message and traceback. The problem is that finally
is guaranteed so I can't return anything inside else
block.
This code works if some Exception
is raised but it doesn't work if there is no Exception
. In such case, I want just return {'success':True}
.
So from this code:
def foo():
try:
#some code
return {'success':True}
except FirstException:
tb = traceback.format_exc()
msg = 'There was FirstExc'
return {'success':False,
'tb':tb,
'msg':msg}
except SecondException:
tb = traceback.format_exc()
msg = 'There was SecondExc'
return {'success':False,
'tb':tb,
'msg':msg}
...
I want not to repeat returns
. I tried:
def foo():
try:
pass
except FirstException:
tb = traceback.format_exc()
msg = 'There was FirstExc'
except SecondException:
tb = traceback.format_exc()
msg = 'There was SecondExc'
else:
return {'success':True}
finally:
return {'success':False,
'tb':tb,
'msg':msg}
Do you know how to do it? I know I could put return {'success':True}
into try
block, remove finally
and else
blocks and add return {'success':False,'tb':tb,'msg':msg}
into each except
block but there are many except
blocks so the code would be repeated multiple times.
Is there another option?
Upvotes: 1
Views: 861
Reputation: 43196
def foo():
success = False
try:
pass
except FirstException:
tb = traceback.format_exc()
msg = 'There was FirstExc'
except SecondException:
tb = traceback.format_exc()
msg = 'There was SecondExc'
else:
success = True
finally:
return {'success':success,
'tb':tb,
'msg':msg} if not success else {'success':success}
Alternative:
def foo():
result = {"success": False}
try:
pass
except FirstException:
result['tb'] = traceback.format_exc()
result['msg'] = 'There was FirstExc'
except SecondException:
result['tb'] = traceback.format_exc()
result['msg'] = 'There was SecondExc'
else:
result['success'] = True
finally:
return result
Slight variation of the above:
def foo():
result = {"success": False}
try:
pass
except FirstException:
result.update({'tb': traceback.format_exc(), 'msg': 'There was FirstExc'})
except SecondException:
result.update({'tb': traceback.format_exc(), 'msg': 'There was SecondExc'})
else:
result['success'] = True
finally:
return result
Upvotes: 1
Reputation: 1123440
Don't use a finally
block. You want to return False
for exceptions only, True
otherwise; returning in a finally
always applies for both cases.
You could either return from both except
suites, or combine the suites.
Returning from both leads to more repetition:
def foo():
try:
pass
except FirstException:
tb = traceback.format_exc()
msg = 'There was FirstExc'
return {'success':False,
'tb':tb,
'msg':msg}
except SecondException:
tb = traceback.format_exc()
msg = 'There was SecondExc'
return {'success':False,
'tb':tb,
'msg':msg}
else:
return {'success':True}
You can combine the except
suites into one:
def foo():
try:
pass
except (FirstException, SecondException) as e:
tb = traceback.format_exc()
exception_type = 'FirstExc' if isinstance(e, FirstException) else 'SecondExc'
msg = 'There was {}'.format(exception_type)
return {'success':False,
'tb':tb,
'msg':msg}
else:
return {'success':True}
Another option is to build the return value first, then add information as needed:
def foo():
result = {'success': True}
try:
pass
except FirstException:
tb = traceback.format_exc()
msg = 'There was FirstExc'
result = {'success': False, 'tb': tb, 'msg': msg}
except SecondException:
tb = traceback.format_exc()
msg = 'There was SecondExc'
result = {'success': False, 'tb': tb, 'msg': msg}
finally:
return result
This isn't really all that different from the return
-from-the-except-suite option however.
Upvotes: 3