Executive summary: 1. Don't distinguish exceptions if it won't make a difference to how you handle them (Andrew also makes this point, and I think it's implicit in MAL's post about exception vs. the reason as well).
2. Usefully introducing more fine-grained exceptions requires that *other* people use them when *you* want them to. Both introspection into my own behavior and the complaint about "shitty corporate systems" suggests that's a "Not Gonna Happen" for all of the proposed exceptions (I think this is Steven d'Aprano's point, too). Ram Rachum writes: > If I do this: > >>> x, y = range(3) > It would be nice if the operation above raised UnpackingOverflowError, > which will be a subclass of UnpackingError, along with > UnpackingUnderflowError. UnpackingError can be a subclass of ValueError, > for backward compatibility. It's not a matter of backward compatibility (unless the Exception class to raise was chosen incorrectly in the first place). The point of distinguishing among Exceptions is that you want to handle them differently. But there's not much you can do with a ValueError or TypeError, because Python implements the "termination model" of exception handling. That is, the program stops what it's doing, and throws away all the work done to that point, including the continuation. It's generally going to be somewhere between impractical and impossible to determine how to fix the input to the computation and restart it. You either need to fix the program and run it on the same inputs, or go on to the next input. Even if you raise a specific subclass, I'm probably going to handle it the same as any other ValueError. On the other hand, there are a plethora of environment errors, such as 3 suberrors of ConnectionError, at least 6 different errors related to opening filesystem objects, and so on. Why? Because there are well- known, common strategies allowing programs to recover from such errors, and programs that catch them are prepared for them with specific handlers for each such exception. I admit I don't recall offhand ever making a pragmatic distinction between TypeError and ValueError myself, except that ValueErrors are often validation errors (eg, a typo), while TypeErrors are invariably a logic error in my experience. But that's a difference in how I respond, not in how my program does. So the principle "don't make distinctions without a difference" isn't followed 100% (at least in terms of my personal pragmatics). But nothing's perfect. The best we can do is to not make things worse. > Similarly, if I did this: > > >>> def f(x, y): return x + y > >>> f(1) > > I would get a TypeError. Would be a lot cooler if I got > MissingArgumentsError, which would be a subclass of SignatureError, which > would be a subclass of TypeError. Cool, maybe, but the relevant question for distinguishing a new exception is how would your *program* respond differently to a different subclass of SignatureError or TypeError? > There are 2 reasons I want this: > > 1. When I'm writing a try..except clause, I want to catch a specific > exception like MissingArgumentsError rather than ValueError or TypeError. > They're too ubiquitous. I don't want some other unexpected failure > producing the same ValueError and triggering my except clause. If you're writing the code that raises the Exception, I see no problem except your willingness to define the appropriate subclasses of ValueError. :-) For SomebodyElse'sCode, here's the rub: > 2. When I get an error, especially from some shitty corporate system that > truncates the traceback, I want to get as many hints as possible about what > went wrong. Why do you think "shitty corporate systems" (or quick hacks on PyPI) are going to use fine-grained exceptions (a) correctly (b) at all? (This is a real question, despite my obvious priors as to the answer.) > It's true that today, most Python exceptions have good text in their > message, like "TypeError: f() missing 1 required positional argument: 'y'". > But that isn't guaranteed everywhere, and specific exception types could > help. I don't see much chance of that pragmatically. I write a lot of code that just raises RuntimeError because I don't feel like looking up and figuring out the appropriate subclass. Some of that code makes it into production, to my later chagrin. (Mostly not: "replace all RuntimeErrors with something appropriate" is on my personal review checklist. :-) IMO, if developers aren't willing to write a descriptive message, the effort to choose a specific exception appropriately is unlikely to be worth it to them. That effort is at best strictly convex, and quite possibly exponential, in the number of Exceptions defined. _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/EFGFSE2V6BRZOPHJ4IK2IBTSCXSOL7MS/ Code of Conduct: http://python.org/psf/codeofconduct/