Exception Reorg PEP checked in

OK, once the cron job comes around and is run, http://www.python.org/peps/pep-0348.html will not be a 404 but be the latest version of the PEP. Differences since my last public version is that it has BaseException/Exception as the naming hierarchy, Warning inherits from Exception, UserException is UserError, and StandardError inherits from Exception. I also added better annotations on the tree for noticing where inheritance changed and whether it become broader (and thus had a new exception in its MRO) or more restrictive (and thus lost an exception). Basically everything that Guido has brought up today (08-03). I may have made some mistakes changing over to BaseException/Exception thanks to their names being so similar and tossing back in StandardError so if people catch what seems like odd sentences that is why (obviously let me know of the mistake). -Brett

Brett Cannon wrote:
If/when you add a "Getting there from here" section, it would be worth noting that there are a few basic strategies to be applied: - for new exceptions: - just add them in release 2.x - for name changes: - add the new name as an alias in release 2.x - deprecate the old name in release 2.x - delete the old name in release 2.(x+1) - to switch inheritance to a new exception type: - add the inheritance to the new parent in release 2.x - delete the inheritance from the old parent in release 3.0 - to switch inheritance to an existing exception type: - add the inheritance to the new parent in release 3.0 - delete the inheritance from the old parent in release 3.0 Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.blogspot.com

Nick Coghlan wrote:
If/when you add a "Getting there from here" section, it would be worth noting that there are a few basic strategies to be applied:
Eh, never mind. It's already there ;) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.blogspot.com

Brett Cannon wrote (in the PEP):
I think this argues against your own hierarchy, since you _did_ call the parent exception CriticalError. By your argument above, that suggests KeyboardInterrupt doesn't belong there ;) In practice, whether KeyboardInterrupt inherits from ControlFlowException or CriticalError shouldn't be a big deal - the important thing is to get it out from under Exception and StandardError. At which point, the naming issue is enough to incline me towards christening it a ControlFlowException. It gets all the 'oddly named' exceptions into one place. Additionally, consider that a hypothetical ThreadExit exception (used to terminate a thread semi-gracefully) would also clearly belong under ControlFlowException. That is, just because something is asynchronous with respect to the currently executing code doesn't necessarily make it an error (yes, I know I argued the opposite point the other day. . .). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.blogspot.com

On 8/4/05, Nick Coghlan <ncoghlan@gmail.com> wrote:
=) Drawback of having names swapped in and out so many times.
In general, probably.
Good point. I think I would like to see Guido's preference for this since it feels like it should be under CriticalError.
Another good point. I am leaning towards moving it now, but I still would like to hear Guido's preference, if he has one. -Brett

Since I forgot to mention it in the last couple of messages - this version looks very good. The transition strategy section makes it a lot more meaningful. Brett Cannon wrote (in the PEP):
Nice trick with figuring out how to raise the deprecation warning :) (That line was going to read 'Why not just create an alias?', but then I worked out what you were doing, and why you were doing it) One case that this doesn't completely address is NameError, as it is the only renamed exception which currently has a subclass. In this case, I think that during the transmition phase, all three of the 'Unbound*Error' exceptions should inherit from NameError, with NameError inheriting from NamespaceError. I believe it should still be possible to get the deprecation warning to work correctly in this case (by not raising the warning when a subclass is instantiated). In the 'just a type' category, WeakReferenceError should still be under StandardError in the hierarchy. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.blogspot.com

On 8/4/05, Nick Coghlan <ncoghlan@gmail.com> wrote:
Since I forgot to mention it in the last couple of messages - this version looks very good. The transition strategy section makes it a lot more meaningful.
Great to hear!
Thanks.
Ah, didn't think about that issue. Yeah, as long as you don't call a superclass' __init__ it should still work.
In the 'just a type' category, WeakReferenceError should still be under StandardError in the hierarchy.
Yeah, that is an error from trying adding StandardError back in. -Brett

On 8/4/05, Brett Cannon <bcannon@gmail.com> wrote:
Currently, when the "recursion limit" is reached, a RuntimeError is raised. RuntimeError is in the PEP renamed to UserError. UserError is in the new hierarchy located below StandardError, below Exception. I think that in the new hierarchy this error should be in the same "critical" category as MemoryError. (MemoryError includes general stack overflow.) - Willem

In general the PEP looks really good now! On 8/4/05, Willem Broekema <metawilm@gmail.com> wrote:
No. Usually, a recursion error is a simple bug in the code, no different from a TypeError or NameError etc. This does contradict my earlier claim that Python itself doesn't use RuntimeError; I think I'd be happier if it remained RuntimeError. (I think there are a few more uses of it inside Python itself; I don't think it's worth inventing new exceptions for all these.) -- --Guido van Rossum (home page: http://www.python.org/~guido/)

On 8/4/05, Guido van Rossum <gvanrossum@gmail.com> wrote:
I just realized that keeping RuntimeError still does not resolve the issue that the name kind of sucks for realizing intrinsically that it is for quick-and-dirty exceptions (or am I the only one who thinks this?). Should we toss in a subclass called SimpleError? -Brett

On 8/5/05, Brett Cannon <bcannon@gmail.com> wrote:
I don't think so. People should feel free to use whatever pre-existing exception they like, even Exception. -- --Guido van Rossum (home page: http://www.python.org/~guido/)

Brett Cannon <bcannon@gmail.com> wrote:
Much Python code I've looked at uses ValueError for this purpose. Would adding a special exception add much utility? Charles -- ----------------------------------------------------------------------- Charles Cazabon <python@discworld.dyndns.org> GPL'ed software available at: http://pyropus.ca/software/ -----------------------------------------------------------------------

What are these new exceptions for? Under what circumstances are they raised? Why is this necessary or an improvement?
This will cause problems when a library raises the exception under the new name and an app tries to catch the old name. So the standard lib (or any other lib) cannot raise the new names. Because the stdlib must raise the old names, people will see the old names, continue catching the old names, and the new names will never catch on. Perhaps it'd work out better to have the new names subclass the old names. Then you have to continue catching the old name as long as anyone is raising it, but at least you can raise the new name with impunity. I expect not much code actually raises ReferenceError or NameError besides that internal to python. Thus it would be relatively safe to change all code to catch the new names for those immediately. Lots of code raises RuntimeError, but I bet not very much code explicitly catches it. Oh, but if the stdlib starts raising under the new names, that'll break any code that checks the exact type of the exception against the old name. Boo. It'd be better to somehow raise a DeprecationWarning upon access, yet still result in the same object. Unfortunately I don't think there's any way to do that in python. This lack of ability to deprecate module attributes has bit me several times in other projects as well. Matt Goodall wrote the hack attached at the end in order to move some whole modules around in Nevow. Amazingly it actually seemed to work. :) Something like that won't work for __builtins__, of course, since that's accessed directly with PyDict_Get. All in all I don't really see a real need for these renamings and I don't see a way to do them compatibly so I'm -1 to the whole idea of renaming exceptions.
Removal of Bare except Clauses
A SemanticsWarning will be raised for all bare except clauses.
Does this mean that bare except clauses change meaning to "except Exception" immediately? Or (I hope) did you mean that in Py2.5 they continue doing as they do now, but print a warning to tell you they will be changing in the future? James

On 8/4/05, James Y Knight <foom@fuhm.net> wrote:
Exceptions relating to when a name is not found in a specific namespace (directly related to bytecode). So UnboundFreeError is raised when the interpreter cannot find a variable that is a free variable. UnboundLocalError already exists. UnboundGlobalError is to prevent NameError from being overloaded. UnboundFreeError is to prevent UnboundLocalError from being overloaded
Crap, you're right. Going to have to think about this more.
Well, the new names can go into 2.x but not removed until 3.0 . And there is always a solution. We do control the implementation so something has evil as hacking the exception system to do class-specific checks could work.
They would have a warning for a version, and then change. And this will nost necessarily go into 2.5 . -Brett

I'm curious about why Python lacks FileNotFoundError, PermissionError and the like as subclasses of IOError. Catching IOError and looking at errno to figure out what went wrong seems pretty unpythonic, and I've often wished for built-in subclasses of IOError. I sometimes subclass them myself, but a lot of the time, I'm catching such exceptions as thrown by the standard library. -wsv

Wilfredo Sánchez Vega <wsanchez@wsanchez.net> writes:
I'm curious about why Python lacks FileNotFoundError, PermissionError and the like as subclasses of IOError.
Good question. Lack of effort/inertia?
The py library does this (http://codespeak.net/py).
I sometimes subclass them myself, but a lot of the time, I'm catching such exceptions as thrown by the standard library.
Well, indeed. OTOH, functions like os.open aren't really *meant* to be pythonic. I don't think this is something I can get interested enough in to work on myself. Cheers, mwh -- <spiv> As far as I'm concerned, the meat pie is the ultimate unit of currency. -- from Twisted.Quotes

On 8/14/05, Michael Hudson <mwh@python.net> wrote:
Well, I wonder how often it's needed. My typical use is this: try: f = open(filename) except IOError, err: print "Can't open %s: %s" % (filename, err) return and the error printed contains all the necessary details (in fact it even repeats the filename, so I could probably just say "print err"). Why do you need to know the exact reason for the failure? If you simply want to know whether the file exists, I'd use os.path.exists() or isfile(). (Never mind that this is the sometimes-frowned-upon look-before-you-leap; I think it's often fine.) Also note that providing the right detail can be very OS specific. Python doesn't just run on Unix and Windows. -- --Guido van Rossum (home page: http://www.python.org/~guido/)

(sorry for the delayed reply; vacation) On Aug 14, 2005, at 12:27 PM, Guido van Rossum wrote:
That's fine for log output, but weak for handling the error.
If you're going to wave off the look-before-you-leap argument, I guess you're right in that case, but I think it's a pretty valid argument for a lot of applications. os.path.exists() also has a race condition in the case where the file is deleted between your test for is and the subsequent attempt to access it, so you'd still need to handle that error in the exception handling if you care about correctness. I agree that in many (most?) cases, this can be fudged, but if it's easier to do the correct thing, more people would do the correct thing. In any case, os.path.exists() also doesn't catch permissions errors, and I often find myself wanting to handle those errors specially as well. An example where both are useful is in an HTTP server, where a different status code should be returned to the client depending on success, file not found, permission denied, and other cases. Presently, I (and twisted.web) have to check errno in the IOError exception handler, which is really clunky, and I have to do it fairly often.
Also note that providing the right detail can be very OS specific. Python doesn't just run on Unix and Windows.
File not found is a detectable error case on all platforms, I think. On an OS that doesn't have permissions errors, I wouldn't expect the existence of an exception that isn't used to be a huge portability problem. I can't imagine that checking errno is a more portable solution. These two exist and are quite useful in Java, for whatever that's worth. -wsv

(sorry for the delayed reply; vacation) On Aug 14, 2005, at 12:27 PM, Guido van Rossum wrote:
On 8/14/05, Michael Hudson <mwh@python.net> wrote:
Wilfredo S
That's fine for log output, but weak for handling the error.
If you're going to wave off the look-before-you-leap argument, I guess you're right in that case, but I think it's a pretty valid argument for a lot of applications. os.path.exists() also has a race condition in the case where the file is deleted between your test for is and the subsequent attempt to access it, so you'd still need to handle that error in the exception handling if you care about correctness. I agree that in many (most?) cases, this can be fudged, but if it's easier to do the correct thing, more people would do the correct thing. In any case, os.path.exists() also doesn't catch permissions errors, and I often find myself wanting to handle those errors specially as well. An example where both are useful is in an HTTP server, where a different status code should be returned to the client depending on success, file not found, permission denied, and other cases. Presently, I (and twisted.web) have to check errno in the IOError exception handler, which is really clunky, and I have to do it fairly often.
Also note that providing the right detail can be very OS specific. Python doesn't just run on Unix and Windows.
File not found is a detectable error case on all platforms, I think. On an OS that doesn't have permissions errors, I wouldn't expect the existence of an exception that isn't used to be a huge portability problem. I can't imagine that checking errno is a more portable solution. These two exist and are quite useful in Java, for whatever that's worth. -wsv

Brett Cannon wrote:
If/when you add a "Getting there from here" section, it would be worth noting that there are a few basic strategies to be applied: - for new exceptions: - just add them in release 2.x - for name changes: - add the new name as an alias in release 2.x - deprecate the old name in release 2.x - delete the old name in release 2.(x+1) - to switch inheritance to a new exception type: - add the inheritance to the new parent in release 2.x - delete the inheritance from the old parent in release 3.0 - to switch inheritance to an existing exception type: - add the inheritance to the new parent in release 3.0 - delete the inheritance from the old parent in release 3.0 Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.blogspot.com

Nick Coghlan wrote:
If/when you add a "Getting there from here" section, it would be worth noting that there are a few basic strategies to be applied:
Eh, never mind. It's already there ;) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.blogspot.com

Brett Cannon wrote (in the PEP):
I think this argues against your own hierarchy, since you _did_ call the parent exception CriticalError. By your argument above, that suggests KeyboardInterrupt doesn't belong there ;) In practice, whether KeyboardInterrupt inherits from ControlFlowException or CriticalError shouldn't be a big deal - the important thing is to get it out from under Exception and StandardError. At which point, the naming issue is enough to incline me towards christening it a ControlFlowException. It gets all the 'oddly named' exceptions into one place. Additionally, consider that a hypothetical ThreadExit exception (used to terminate a thread semi-gracefully) would also clearly belong under ControlFlowException. That is, just because something is asynchronous with respect to the currently executing code doesn't necessarily make it an error (yes, I know I argued the opposite point the other day. . .). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.blogspot.com

On 8/4/05, Nick Coghlan <ncoghlan@gmail.com> wrote:
=) Drawback of having names swapped in and out so many times.
In general, probably.
Good point. I think I would like to see Guido's preference for this since it feels like it should be under CriticalError.
Another good point. I am leaning towards moving it now, but I still would like to hear Guido's preference, if he has one. -Brett

Since I forgot to mention it in the last couple of messages - this version looks very good. The transition strategy section makes it a lot more meaningful. Brett Cannon wrote (in the PEP):
Nice trick with figuring out how to raise the deprecation warning :) (That line was going to read 'Why not just create an alias?', but then I worked out what you were doing, and why you were doing it) One case that this doesn't completely address is NameError, as it is the only renamed exception which currently has a subclass. In this case, I think that during the transmition phase, all three of the 'Unbound*Error' exceptions should inherit from NameError, with NameError inheriting from NamespaceError. I believe it should still be possible to get the deprecation warning to work correctly in this case (by not raising the warning when a subclass is instantiated). In the 'just a type' category, WeakReferenceError should still be under StandardError in the hierarchy. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.blogspot.com

On 8/4/05, Nick Coghlan <ncoghlan@gmail.com> wrote:
Since I forgot to mention it in the last couple of messages - this version looks very good. The transition strategy section makes it a lot more meaningful.
Great to hear!
Thanks.
Ah, didn't think about that issue. Yeah, as long as you don't call a superclass' __init__ it should still work.
In the 'just a type' category, WeakReferenceError should still be under StandardError in the hierarchy.
Yeah, that is an error from trying adding StandardError back in. -Brett

On 8/4/05, Brett Cannon <bcannon@gmail.com> wrote:
Currently, when the "recursion limit" is reached, a RuntimeError is raised. RuntimeError is in the PEP renamed to UserError. UserError is in the new hierarchy located below StandardError, below Exception. I think that in the new hierarchy this error should be in the same "critical" category as MemoryError. (MemoryError includes general stack overflow.) - Willem

In general the PEP looks really good now! On 8/4/05, Willem Broekema <metawilm@gmail.com> wrote:
No. Usually, a recursion error is a simple bug in the code, no different from a TypeError or NameError etc. This does contradict my earlier claim that Python itself doesn't use RuntimeError; I think I'd be happier if it remained RuntimeError. (I think there are a few more uses of it inside Python itself; I don't think it's worth inventing new exceptions for all these.) -- --Guido van Rossum (home page: http://www.python.org/~guido/)

On 8/4/05, Guido van Rossum <gvanrossum@gmail.com> wrote:
I just realized that keeping RuntimeError still does not resolve the issue that the name kind of sucks for realizing intrinsically that it is for quick-and-dirty exceptions (or am I the only one who thinks this?). Should we toss in a subclass called SimpleError? -Brett

On 8/5/05, Brett Cannon <bcannon@gmail.com> wrote:
I don't think so. People should feel free to use whatever pre-existing exception they like, even Exception. -- --Guido van Rossum (home page: http://www.python.org/~guido/)

Brett Cannon <bcannon@gmail.com> wrote:
Much Python code I've looked at uses ValueError for this purpose. Would adding a special exception add much utility? Charles -- ----------------------------------------------------------------------- Charles Cazabon <python@discworld.dyndns.org> GPL'ed software available at: http://pyropus.ca/software/ -----------------------------------------------------------------------

What are these new exceptions for? Under what circumstances are they raised? Why is this necessary or an improvement?
This will cause problems when a library raises the exception under the new name and an app tries to catch the old name. So the standard lib (or any other lib) cannot raise the new names. Because the stdlib must raise the old names, people will see the old names, continue catching the old names, and the new names will never catch on. Perhaps it'd work out better to have the new names subclass the old names. Then you have to continue catching the old name as long as anyone is raising it, but at least you can raise the new name with impunity. I expect not much code actually raises ReferenceError or NameError besides that internal to python. Thus it would be relatively safe to change all code to catch the new names for those immediately. Lots of code raises RuntimeError, but I bet not very much code explicitly catches it. Oh, but if the stdlib starts raising under the new names, that'll break any code that checks the exact type of the exception against the old name. Boo. It'd be better to somehow raise a DeprecationWarning upon access, yet still result in the same object. Unfortunately I don't think there's any way to do that in python. This lack of ability to deprecate module attributes has bit me several times in other projects as well. Matt Goodall wrote the hack attached at the end in order to move some whole modules around in Nevow. Amazingly it actually seemed to work. :) Something like that won't work for __builtins__, of course, since that's accessed directly with PyDict_Get. All in all I don't really see a real need for these renamings and I don't see a way to do them compatibly so I'm -1 to the whole idea of renaming exceptions.
Removal of Bare except Clauses
A SemanticsWarning will be raised for all bare except clauses.
Does this mean that bare except clauses change meaning to "except Exception" immediately? Or (I hope) did you mean that in Py2.5 they continue doing as they do now, but print a warning to tell you they will be changing in the future? James

On 8/4/05, James Y Knight <foom@fuhm.net> wrote:
Exceptions relating to when a name is not found in a specific namespace (directly related to bytecode). So UnboundFreeError is raised when the interpreter cannot find a variable that is a free variable. UnboundLocalError already exists. UnboundGlobalError is to prevent NameError from being overloaded. UnboundFreeError is to prevent UnboundLocalError from being overloaded
Crap, you're right. Going to have to think about this more.
Well, the new names can go into 2.x but not removed until 3.0 . And there is always a solution. We do control the implementation so something has evil as hacking the exception system to do class-specific checks could work.
They would have a warning for a version, and then change. And this will nost necessarily go into 2.5 . -Brett

I'm curious about why Python lacks FileNotFoundError, PermissionError and the like as subclasses of IOError. Catching IOError and looking at errno to figure out what went wrong seems pretty unpythonic, and I've often wished for built-in subclasses of IOError. I sometimes subclass them myself, but a lot of the time, I'm catching such exceptions as thrown by the standard library. -wsv

Wilfredo Sánchez Vega <wsanchez@wsanchez.net> writes:
I'm curious about why Python lacks FileNotFoundError, PermissionError and the like as subclasses of IOError.
Good question. Lack of effort/inertia?
The py library does this (http://codespeak.net/py).
I sometimes subclass them myself, but a lot of the time, I'm catching such exceptions as thrown by the standard library.
Well, indeed. OTOH, functions like os.open aren't really *meant* to be pythonic. I don't think this is something I can get interested enough in to work on myself. Cheers, mwh -- <spiv> As far as I'm concerned, the meat pie is the ultimate unit of currency. -- from Twisted.Quotes

On 8/14/05, Michael Hudson <mwh@python.net> wrote:
Well, I wonder how often it's needed. My typical use is this: try: f = open(filename) except IOError, err: print "Can't open %s: %s" % (filename, err) return and the error printed contains all the necessary details (in fact it even repeats the filename, so I could probably just say "print err"). Why do you need to know the exact reason for the failure? If you simply want to know whether the file exists, I'd use os.path.exists() or isfile(). (Never mind that this is the sometimes-frowned-upon look-before-you-leap; I think it's often fine.) Also note that providing the right detail can be very OS specific. Python doesn't just run on Unix and Windows. -- --Guido van Rossum (home page: http://www.python.org/~guido/)

(sorry for the delayed reply; vacation) On Aug 14, 2005, at 12:27 PM, Guido van Rossum wrote:
That's fine for log output, but weak for handling the error.
If you're going to wave off the look-before-you-leap argument, I guess you're right in that case, but I think it's a pretty valid argument for a lot of applications. os.path.exists() also has a race condition in the case where the file is deleted between your test for is and the subsequent attempt to access it, so you'd still need to handle that error in the exception handling if you care about correctness. I agree that in many (most?) cases, this can be fudged, but if it's easier to do the correct thing, more people would do the correct thing. In any case, os.path.exists() also doesn't catch permissions errors, and I often find myself wanting to handle those errors specially as well. An example where both are useful is in an HTTP server, where a different status code should be returned to the client depending on success, file not found, permission denied, and other cases. Presently, I (and twisted.web) have to check errno in the IOError exception handler, which is really clunky, and I have to do it fairly often.
Also note that providing the right detail can be very OS specific. Python doesn't just run on Unix and Windows.
File not found is a detectable error case on all platforms, I think. On an OS that doesn't have permissions errors, I wouldn't expect the existence of an exception that isn't used to be a huge portability problem. I can't imagine that checking errno is a more portable solution. These two exist and are quite useful in Java, for whatever that's worth. -wsv

(sorry for the delayed reply; vacation) On Aug 14, 2005, at 12:27 PM, Guido van Rossum wrote:
On 8/14/05, Michael Hudson <mwh@python.net> wrote:
Wilfredo S
That's fine for log output, but weak for handling the error.
If you're going to wave off the look-before-you-leap argument, I guess you're right in that case, but I think it's a pretty valid argument for a lot of applications. os.path.exists() also has a race condition in the case where the file is deleted between your test for is and the subsequent attempt to access it, so you'd still need to handle that error in the exception handling if you care about correctness. I agree that in many (most?) cases, this can be fudged, but if it's easier to do the correct thing, more people would do the correct thing. In any case, os.path.exists() also doesn't catch permissions errors, and I often find myself wanting to handle those errors specially as well. An example where both are useful is in an HTTP server, where a different status code should be returned to the client depending on success, file not found, permission denied, and other cases. Presently, I (and twisted.web) have to check errno in the IOError exception handler, which is really clunky, and I have to do it fairly often.
Also note that providing the right detail can be very OS specific. Python doesn't just run on Unix and Windows.
File not found is a detectable error case on all platforms, I think. On an OS that doesn't have permissions errors, I wouldn't expect the existence of an exception that isn't used to be a huge portability problem. I can't imagine that checking errno is a more portable solution. These two exist and are quite useful in Java, for whatever that's worth. -wsv
participants (9)
-
Brett Cannon
-
Charles Cazabon
-
Guido van Rossum
-
James Y Knight
-
Michael Hudson
-
Nick Coghlan
-
Wilfredo Sánchez Vega
-
Wilfredo Sánchez Vega
-
Willem Broekema