PEP 352 Transition Plan
I don't follow why the PEP deprecates catching a category of exceptions in a different release than it deprecates raising them. Why would a release allow catching something that cannot be raised? I must be missing something here. Raymond
On 10/28/05, Raymond Hettinger
I don't follow why the PEP deprecates catching a category of exceptions in a different release than it deprecates raising them. Why would a release allow catching something that cannot be raised? I must be missing something here.
So conforming code can catch exceptions raised by not-yet conforming code. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
Why would a release allow catching something that cannot be raised? I must be missing something here.
So conforming code can catch exceptions raised by not-yet conforming code.
That makes sense. What was the rationale for pushing the deprecation of __getitem__ and args back to Py2.8? Is the there a disadvantage for doing it earlier? On the flip side, is there any reason it has to be done at all prior to Py3.0? That change seems orthogonal to the rest of the proposal and has its own pluses and minuses (simplification on the plus-side and code-breakage on the minus-side). FWIW, the args tuple does have a legitimate use case as one solution to the problem of exception chaining (keeping the old info intact, but adding new info as an extra field): try: raise TypeError('inner detail') except TypeError, e: args = e.args + ('outer context',) raise TypeError(*args) Raymond
On 10/28/05, Raymond Hettinger
Why would a release allow catching something that cannot be raised? I must be missing something here.
So conforming code can catch exceptions raised by not-yet conforming code.
That makes sense.
What was the rationale for pushing the deprecation of __getitem__ and args back to Py2.8? Is the there a disadvantage for doing it earlier? On the flip side, is there any reason it has to be done at all prior to Py3.0? That change seems orthogonal to the rest of the proposal and has its own pluses and minuses (simplification on the plus-side and code-breakage on the minus-side).
I thought that there was no exact rush on their removal. And I suspect the later versions of the 2.x branch will be used to help ease transition to Python 3, so I figured pushing it to 2.8 seemed like a good idea. I could even push it all the way to 2.9 if people prefer.
FWIW, the args tuple does have a legitimate use case as one solution to the problem of exception chaining (keeping the old info intact, but adding new info as an extra field):
try: raise TypeError('inner detail') except TypeError, e: args = e.args + ('outer context',) raise TypeError(*args)
Interesting point, but I think that chaining should have more concrete support ala PEP 344 or some other mechanism. I think most people agree that exception chaining is important enough to have better support than some implied way of a causing exception to be passed along. Perhaps something more along the lines of: try: raise TypeError("inner detail") except TypeError, e: raise TypeError("outer detail", cause=e) where BaseException then has a 'cause' attribute that is set to None by default or some specific object that is passed in as the second argument to the constructor. -Brett
Brett Cannon wrote:
Interesting point, but I think that chaining should have more concrete support ala PEP 344 or some other mechanism. I think most people agree that exception chaining is important enough to have better support than some implied way of a causing exception to be passed along. Perhaps something more along the lines of:
try: raise TypeError("inner detail") except TypeError, e: raise TypeError("outer detail", cause=e)
where BaseException then has a 'cause' attribute that is set to None by default or some specific object that is passed in as the second argument to the constructor.
Another point in PEP 352's favour, is that it makes it far more feasible to implement something like PEP 344 by providing "__traceback__" and "__prev_exc__" attributes on BaseException. The 'raise' statement could then take care of setting them appropriately if it was given an instance of BaseException to raise. Actually, that brings up another question - PEP 352 says it will require objects that "inherit from BaseException". Does that mean that either subtypes or instances of BaseException will be acceptable? Or does it just mean instances? If the latter, how will that affect the multi-argument forms of 'raise'? Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia --------------------------------------------------------------- http://boredomandlaziness.blogspot.com
[Nick Coghlan]
Another point in PEP 352's favour, is that it makes it far more feasible to implement something like PEP 344 by providing "__traceback__" and "__prev_exc__" attributes on BaseException.
The 'raise' statement could then take care of setting them appropriately if it was given an instance of BaseException to raise.
IMO, there is no reason to take e.args out of the Py2.x series. Take-aways should be left for Py3.0. The existence of a legitimate use case means that there may be working code in the field that would be broken unnecessarily. Nothing is gained by this breakage. If 344 gets accepted and implemented, that's great. Either way, there is no rationale for chopping this long standing feature before 3.0. IIRC, that was the whole point of 3.0 -- we could take out old stuff that had been replaced by new and better things; otherwise, we would simply deprecate old-style classes and be done with it in Py2.5 or Py2.6. Raymond
On 10/28/05, Nick Coghlan
Brett Cannon wrote:
Interesting point, but I think that chaining should have more concrete support ala PEP 344 or some other mechanism. I think most people agree that exception chaining is important enough to have better support than some implied way of a causing exception to be passed along. Perhaps something more along the lines of:
try: raise TypeError("inner detail") except TypeError, e: raise TypeError("outer detail", cause=e)
where BaseException then has a 'cause' attribute that is set to None by default or some specific object that is passed in as the second argument to the constructor.
Another point in PEP 352's favour, is that it makes it far more feasible to implement something like PEP 344 by providing "__traceback__" and "__prev_exc__" attributes on BaseException.
The 'raise' statement could then take care of setting them appropriately if it was given an instance of BaseException to raise.
Yep. This is why having a guaranteed API is so handy for exceptions. And actually PEP 3000 says that exceptions are supposed to gain a traceback attribute. But that can be another PEP if PEP 344 doesn't make it.
Actually, that brings up another question - PEP 352 says it will require objects that "inherit from BaseException". Does that mean that either subtypes or instances of BaseException will be acceptable? Or does it just mean instances? If the latter, how will that affect the multi-argument forms of 'raise'?
I don't see how a multi-argument 'raise' changes the situation any. ``raise BaseException`` and ``raise BaseException()`` must both be supported which means isinstance() or issubtype() will be used (unless Python 3 bans raising a class or something). -Brett -Brett
I've made a final pass over PEP 352, mostly fixing the __str__, __unicode__ and __repr__ methods to behave more reasonably. I'm all for accepting it now. Does anybody see any last-minute show-stopping problems with it? As always, http://python.org/peps/pep-0352.html -- --Guido van Rossum (home page: http://www.python.org/~guido/)
[Guido van Rossum]
I've made a final pass over PEP 352, mostly fixing the __str__, __unicode__ and __repr__ methods to behave more reasonably. I'm all for accepting it now. Does anybody see any last-minute show-stopping problems with it?
I did not follow the thread, so maybe I'm out in order, be kind with me. After having read PEP 352, it is not crystal clear whether in: try: ... except: ... the "except:" will mean "except BaseException:" or "except Exception:". I would except the first, but the text beginning the section titled "Exception Hierarchy Changes" suggests it could mean the second, without really stating it. Let me argue that "except BaseException:" is preferable. First, because there is no reason to load a bare "except:" by anything but a very simple and clean meaning, like the real base of the exception hierarchy. Second, as a bare "except:" is not considered good practice on average, it would be counter-productive trying to figure out ways to make it more frequently _usable_. -- François Pinard http://pinard.progiciels-bpi.ca
[Guido van Rossum]
I've made a final pass over PEP 352, mostly fixing the __str__, __unicode__ and __repr__ methods to behave more reasonably. I'm all for accepting it now. Does anybody see any last-minute show-stopping problems with it?
[François]
I did not follow the thread, so maybe I'm out in order, be kind with me.
After having read PEP 352, it is not crystal clear whether in:
try: ... except: ...
the "except:" will mean "except BaseException:" or "except Exception:". I would except the first, but the text beginning the section titled "Exception Hierarchy Changes" suggests it could mean the second, without really stating it.
This is probably a leftover from PEP 348, which did have a change for bare 'except:' in mind. PEP 352 doesn't propose to change its meaning, and if there are words that suggest this, they should be removed. Until Python 3.0, it will not change its meaning from what it is now; this is because until then, it is still *possible* (though it will become deprecated behavior) to raise string exceptions or classes that don't inherit from BaseException.
Let me argue that "except BaseException:" is preferable. First, because there is no reason to load a bare "except:" by anything but a very simple and clean meaning, like the real base of the exception hierarchy. Second, as a bare "except:" is not considered good practice on average, it would be counter-productive trying to figure out ways to make it more frequently _usable_.
What bare 'except:' will mean in Python 3.0, and whether it is even allowed at all, is up for discussion -- it will have to be a new PEP. Personally, I think bare 'except:' should be removed from the language in Python 3.0, so that all except clauses are explicit in what they catch and there isn't any confusion over whether KeyboardInterrupt, SystemExit etc. are included or not. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
On 10/29/05, Nick Coghlan
Another point in PEP 352's favour, is that it makes it far more feasible to implement something like PEP 344 by providing "__traceback__" and "__prev_exc__" attributes on BaseException.
Not sure if I'm fully in-context here, but watch out for __traceback__ and garbage collection, since the traceback objects refer to all the frames. I expect there's a significant amount of code out there that expects Exception instances to be reasonably persistent. At least Twisted does, with its encapsulation of Exceptions for the purposes of asynchrony -- Failure objects. These Failure objects also refer to tracebacks, but we had to be very careful about deleting them fairly quickly because of GC issues. After deletion they simply contain an inert, basically stringified copy of the traceback. On an only semi-related note, at one point I tried making it possible to have longer-lived Traceback objects that could be reraised, but found it very hard to do, at least with my self-imposed requirement of keeping it in an extension module. http://mail.python.org/pipermail/python-dev/2005-September/056091.html -- Twisted | Christopher Armstrong: International Man of Twistery Radix | -- http://radix.twistedmatrix.com | Release Manager, Twisted Project \\\V/// | -- http://twistedmatrix.com |o O| | w----v----w-+
On 10/28/05, Raymond Hettinger
I don't follow why the PEP deprecates catching a category of exceptions in a different release than it deprecates raising them. Why would a release allow catching something that cannot be raised? I must be missing something here.
Presumably because they CAN still be raised; attempting to do so provokes a warning, not an error. It also facilitates upgrading from old versions of Python. You can work to eliminate cases where the exceptions are raised while still handling them if they do get raised. -- Adam Olsen, aka Rhamphoryncus
participants (7)
-
Adam Olsen
-
Brett Cannon
-
Christopher Armstrong
-
François Pinard
-
Guido van Rossum
-
Nick Coghlan
-
Raymond Hettinger