gevial
gevial

Reputation: 160

Handling multiple exceptions in Python

I want to handle different exceptions in such way that there will be common handling for any exception and additional specific handling for subprocess.CalledProcessError. Like this:

try:
    check_output(shlex.split(rsync_cmd))
except CalledProcessException as e:
    # do some stuff
    # do common exception handling
except Exception as e:
    # do the same common handling

I don't want to duplicate code so currently I end up with this code:

try:
    check_output(shlex.split(rsync_cmd))
except Exception as e:
    if isinstance(e, CalledProcessError) and e.returncode == 24:
        # do some stuff
    # do common handling

What's the best practice to run specific code for one exception and to run common code for all exceptions at the same time?

Upvotes: 0

Views: 6465

Answers (4)

PM 2Ring
PM 2Ring

Reputation: 55469

You could use nested try:...except blocks. I don't think it's a satisfactory solution, but here's a simple example.

for i in (1, 0, 'z'):
    try:
        try:
            print(i, end=' ')
            x = 1 / i
            print(x)
        except TypeError as e:
            print(e)
            raise
        except ZeroDivisionError as e:
            print(e)
            raise
    except (TypeError, ZeroDivisionError) as e:
        print('Common stuff', e)

output

1 1.0
0 float division
Common stuff float division
z unsupported operand type(s) for /: 'int' and 'str'
Common stuff unsupported operand type(s) for /: 'int' and 'str'

Tested on Python 2.6.6, with from __future__ import print_function, division

Upvotes: 3

Ilja Everilä
Ilja Everilä

Reputation: 52929

Create a function that handles the common operations. That's what functions are for.

def common_exception_handling(e):
    # do stuff with e
    return  # possibly something

# ...

try:
    check_output(shlex.split(rsync_cmd))
except CalledProcessException as e:
    # do some stuff
    common_exception_handling(e)
except Exception as e:
    common_exception_handling(e)

Upvotes: 1

Mp0int
Mp0int

Reputation: 18727

Use inheritance in your exceptions.

class GeneralException(Exception)
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

class SpecificException(GeneralException)
    def __init__(self, value):
        self.value = value
        super(SpecificException, self).__init__()
    def __str__(self):
        super(SpecificException, self).__str__()
        return repr(self.value)

Base logic is, you trigger SpecificExceptions and they all super call GeneralException to execure related operations

Upvotes: 1

Eugene Lisitsky
Eugene Lisitsky

Reputation: 12845

You may check error not only against class, but also a tuple of classes. In each branch you may check specific properties.

    try:
           n=0/0
    except (IOError, ImportError) as e:
         print(1)
    except (NameError) as e:
         print(2)

    Traceback (most recent call last):
    File "<input>", line 2, in <module>
         n=0/0
    ZeroDivisionError: division by zero

Upvotes: 1

Related Questions