Let’s say I have some isolated Python code that processes data produced by some other entity (E.g. a client).
The data I receive may be in incorrect form (e.g. due to client’s sloppiness, data corruption, you name it), so that processing in my Python code will somehow fail, and that will lead to some exception being raised. Let’s assume that the code downstream is just interested in knowing if processing was correct and wrong, and not why it was wrong.
My concern is the following: what is the best practice for raising such exception on a complex bad input? How to organize the exceptions in this case?
Data can turn out to be incorrect in a lot of ways, especially if the correct formatting of the data is complex. In some cases I may easily catch the error myself (e.g. if I find an incorrect magic value, in which case I may raise my FancyCustomizedException), but in others some generic exception could get raised as well (e.g. some ValueException).
Is it OK to say that processing was wrong if any exception is raised (in which case the code downstream will use very a generic (and ugly) try: ... except: ...)?
Is it better to catch all generic exceptions and hide them inside my FancyCustomizedException (in which case the code downstream will use very a less generic try: ... except FancyCustomizedException, e: ..., but I will litter my code with try: ... except: ...)?
Since you seem to have a need for quite some validation I would simply wrap all validation ‘errors’ on a given input in a ValidationSummary object / instance (which contains a list of everything which went wrong) and pass that around instead.
On a more general note: contrary to other languages, structuring program flow by exception handling is common and accepted in Python. A Python idiom related to this is called EAFP (It’s Easier to ask forgiveness then permission).