Reputation: 3751
So, let say I have 3 different calls called something
, something1
and something2
.
and right now, im calling it like
try:
something
something1
something2
except Keyerror as e:
print e
Note that in the above code, if something fails, something1 and something2 will not get executed and so on.
The wanted outcome is
try:
something
except KeyError as e:
print e
try:
something1
except KeyError as e:
print e
try:
something2
except KeyError as e:
print e
How can I achieve the above code without so many try except blocks.
EDIT:
So, the answer I chose as correct worked. But some of the others worked as well. I chose that because it was the simplist and I modified it a little.
Here is my solution based on the answer.
runs = [something, something1, something2]
for func in runs:
try:
func()
except Keyerror as e:
print e
Upvotes: 5
Views: 1113
Reputation: 494
In python3, if you want to input a function with its args and kwargs, you can use the code below:
def safe_do(**statement):
try:
statement['func'](*statement['args'],**statement['kwargs'])
except Exception as e:
print(e)
print(statement['func'])
print(statement['args'])
print(statement['kwargs'])
def divide(a,b):
print(a/b)
safe_do(func=divide,args=[1,0],kwargs={})
In my colab notebook, I presented it.
Upvotes: 0
Reputation: 184345
Here's a little context manager I've used for similar situations:
from contextlib import contextmanager
@contextmanager
def ignoring(*exceptions):
try:
yield
except exceptions or Exception as e:
print e
with ignoring(KeyError):
something()
# you can also put it on the same line if it's just one statement
with ignoring(KeyError): something1()
with ignoring(KeyError): something2()
A Python 3 version could let you parameterize what to do when an exception occurs (the keyword-only arguments are needed here):
from contextlib import contextmanager
@contextmanager
def ignoring(*exceptions, action=print):
try:
yield
except exceptions or Exception as e:
callable(action) and action(e)
Then you could pass in some function other than print
(such as a logger, assumed to be a function named log
) or if you don't want anything, pass in None
(since it checks to see if the action is callable):
with ignoring(KeyError, action=log): something()
Upvotes: 6
Reputation: 653
Other possibility
def mydec(func):
def dec():
try:
func()
except KeyError as e:
print(e)
return dec
@mydec
def f1():
print('a')
@mydec
def f2():
print('b')
raise KeyError('Test')
f1()
f2()
Upvotes: 1
Reputation: 1262
I would go with something like this:
def safe_do(*statements):
for statement, args, kwargs in statements:
try:
statement(*args, **kwargs)
except KeyError as e:
print e
# usage:
safe_do(
(something1, [], {}),
(something2, [], {}),
)
But if you are expecting only one element to be missing in statements than why don't you if
it?
if some_key1 in some_dict1:
something1
if some_key2 in some_dict2:
something2
much more readable and without any magic
Upvotes: 2
Reputation: 3638
This greatly depends on whether or not you're doing similar tasks, or very different tasks. For example, if your something
lines are all very similar you could do the following:
def something(my_dict):
try:
d = my_dict['important_key'] # Just an example, since we
return d # don't know what you're really doing
except KeyError as e:
print e
something(dict1)
something(dict2)
something(dict3)
However, if your tasks are wildly different, this approach may not be applicable. To a certain degree you're asking "How do I write efficient code", and the answer to that depends on what code you're writing.
Upvotes: 0
Reputation: 117781
You could try this, assuming you wrap things in functions:
for func in (something, something1, something2):
try:
func()
except Keyerror as e:
print e
Upvotes: 11