Cripto
Cripto

Reputation: 3751

a cleaner way to approach try except in python

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

Answers (6)

M.Vu
M.Vu

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

kindall
kindall

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

neiesc
neiesc

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

kkonrad
kkonrad

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

Kudzu
Kudzu

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

orlp
orlp

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

Related Questions