I need to make sure that in the event of any error some identical actions and some specific ones occur. Something like this:

try: doing_some_actions except SpecialErrorOne: doing_special_action1 actions_for_all_errors except SpecialErrorTwo: doing_special_action2 actions_for_all_errors except SpecialErrorThree: doing_special_action3 actions_for_all_errors 

How best to do this with minimal code repetition?

If you do this, the exception falls on the screen, bypassing the SpecialError'ы :

 try: doing_some_actions except Exception as ex: actions_for_error raise ex except SpecialErrorOne: doing_special_action1 except SpecialErrorTwo: doing_special_action2 except SpecialErrorThree: doing_special_action3 
  • one
    The best solution may depend on the specific task (you can mention in the question what exceptions are and what actions_for_error, doing_special_actionN represent), for example for OSError, you can use if / elif errno instead of except blocks. To add a log entry in case of any error in a given block of code, you can use your context manager and with -construction around this block. contextlib.ExitStack() allows a variety of strategies to implement. There are many options. - jfs

3 answers 3

You can inherit the base exception class Exception , in which you define specific actions for a specific error, then you need only one except block, which will have the same actions for the error. And doing_special_action call based on the name of the exception.

 class SpecialErrorOne(Exception): def __init__(self): print('Call SpecialErrorOne') class SpecialErrorTwo(Exception): def __init__(self): print('Call SpecialErrorTwo') def actions_for_all_errors(): print('Call actions_for_all_errors') def doing_some_actions(): raise SpecialErrorOne if __name__ == '__main__': try: doing_some_actions() except Exception as ex: if isinstance(ex, SpecialErrorOne): print('doing_special_action1') elif isinstance(ex, SpecialErrorTwo): print('doing_special_action2') actions_for_all_errors() raise 

    You can try this:

     try: doing_some_actions return except SpecialErrorOne: doing_special_action1 except SpecialErrorTwo: doing_special_action2 except SpecialErrorThree: doing_special_action3 actions_for_all_errors 
    • And if an error occurs in one of doing_special_action, which is forwarded to the top? - faoxis
    • Well, in general, it is a good tone to avoid the possibility of errors in error handlers. Wrap in try / except if in doubt. - Vladimir Pavluk

    I would use the pattern design strategy:

    1. The class Action , and from it descendants SpecialAction1 , SpecialAction2 , ..., SpecialActionN already inherited. The general behavior for all reactions to different errors can be written directly in Action
    2. Further, the except block can be reduced to one: except (Error1, Error2, Error3) as e
    3. In the exception type, add an error code with the error_no() method
    4. Having in hand 3, you can generate action classes like this: Action.make(err.error_no()).run() . To do this, you need to write a factory make() method in the base class which, based on the error code, creates an error response class
    • 2
      Python, not Java — you should not fuss. You try to write the whole code sample to realize that this is not the best approach in Python. Even a similar approach: generic functions (functools.singledispatch) parameterized exceptions (should be more elegant than the approach suggested in the answer) would be a brute force in this case (although it depends on the context — the questioner does not recognize which particular case is considered, so it's hard to say ). - jfs
    • Yes. @faoxis needs to clarify its situation. But the design pattern is more than appropriate here. The option of course cumbersome. I do not argue. But familiar and understandable! We do not write the code to get the prize “The shortest code”, but above all so that the code is understandable not only to ourselves, but to colleagues, even those we do not know yet. Using functools.singledispatch not very popular among python-programmers, I clarified this by searching for usage on github - sys_dev
    • The criterion is not the brevity of the code, but its readability, simplicity, clarity, ease of maintenance and expansion. The fact that singledispatch is rarely used and I suggest it as an improvement over your decision should suggest the depth of the shortcomings of the latter. Write a complete example for the solution you are proposing and compare it with the code from the other answers. Abuse of design patterns — a common mistake for beginners (from the category: know just enough to be dangerous — worse than learning from scratch). The fact that you did not immediately give a complete example of the code already speaks about the quality of the solution. - jfs