I'm +0 on finally deprecating the string exceptions. But am -1000 on eliminating implicit instantiation before Py3.0. Right after writing: "In short, implicit instantiation has no advantages other than backwards compatibility ..." I think it would only be fair to add: "If this proposal is adopted, nearly every piece of non-trivial python code that has ever been written would need to be revised or would fail to run. Likewise, most tutorial and book examples would also fail." Raymond Hettinger
Raymond Hettinger wrote:
I'm +0 on finally deprecating the string exceptions. But am -1000 on eliminating implicit instantiation before Py3.0.
I am +1 on deprecating string exceptions for Python 3. Now, since this will end up forcing instances to be created for each raised exception, can we now consider implementing chained exceptions as has been mentioned here numerous times? Since we are going to end up breaking a good amount of code with this (if it happens) we might as well go all-out and get in the features we want. -Brett
can we now consider implementing chained exceptions as has been mentioned here numerous times?
I must have missed that. What are chained exceptions? Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
Greg Ewing wrote:
can we now consider implementing chained exceptions as has been mentioned here numerous times?
I must have missed that. What are chained exceptions?
It was brought up once that raising an exception after another exception was already raised (because of an error in the exception-handling code, raising another exception to change the meaning) causes the original exception to be ignored. It was suggested to keep a reference to the previous exception in the current exception so you could know about all the exceptions that have been raised. Implementation could be easy as adding an attribute to store a reference to any previous exception that someone can look at if they care to. Obviously the reference would be set automatically when an exception is raised and an exception is already pending. I think the open question was whether 'except' clauses should also check the previous exceptions or only the current one. This was discussed on the list between Ping and I think Walter (could be wrong about Walter but I know Ping was involved). Should be in the Summary archive somewhere; just need to find it. =) -Brett
Brett C. wrote:
Greg Ewing wrote:
can we now consider implementing chained exceptions as has been mentioned here numerous times?
I must have missed that. What are chained exceptions?
<SNIP> This was discussed on the list between Ping and I think Walter (could be wrong about Walter but I know Ping was involved). Should be in the Summary archive somewhere; just need to find it. =)
Found it. Raymond apparently instigated the thread: http://mail.python.org/pipermail/python-dev/2003-January/032492.html And it continued into the next month: http://mail.python.org/pipermail/python-dev/2003-February/032864.html And you even contributed to the discussion, Greg =) : http://mail.python.org/pipermail/python-dev/2003-January/032513.html But the original terminology was "exception masking" so that may have been why this didn't ring any bells. For the impatient you can read the last 3 emails I think (especially the absolute last which was authored by Raymond) to get a summary of the ideas proposed. -Brett
Brett C. wrote:
Brett C. wrote:
Greg Ewing wrote:
can we now consider implementing chained exceptions as has been mentioned here numerous times?
I must have missed that. What are chained exceptions?
<SNIP>
This was discussed on the list between Ping and I think Walter (could be wrong about Walter but I know Ping was involved). Should be in the Summary archive somewhere; just need to find it. =)
Found it.
Raymond apparently instigated the thread: http://mail.python.org/pipermail/python-dev/2003-January/032492.html
And it continued into the next month: http://mail.python.org/pipermail/python-dev/2003-February/032864.html
And you even contributed to the discussion, Greg =) : http://mail.python.org/pipermail/python-dev/2003-January/032513.html
But the original terminology was "exception masking" so that may have been why this didn't ring any bells.
For the impatient you can read the last 3 emails I think (especially the absolute last which was authored by Raymond) to get a summary of the ideas proposed.
An open question for exception chaining was which exception type is tested in the except statement, the innermost or the outermost one. I'd say for backwards compatibility reasons this should be the outermost exception, but we could add a new feature to that: Add a new exception subclass named Info that can be used to wrap exceptions without influencing the type of the exception raised. This could be used by code higher up in the call chain to add information to the exception without changing the type that gets caught in the except statement. For example filter() could be changed to add information about the iteration index where the exception happened: class spam: def __getitem__(self, index): if index==42: raise TypeError return None x = filter(None, spam()) this might give: Traceback (most recent call last): File "spam.py", line 8, in ? x = filter(None, foo()) File "spam.py", line 4, in __getitem__ raise TypeError("ouch") TypeError: ouch Info: in filter() at index 42 Bye, Walter Dörwald
Walter Dörwald wrote:
An open question for exception chaining was which exception type is tested in the except statement, the innermost or the outermost one.
I'd say for backwards compatibility reasons this should be the outermost exception,
That's what I was thinking. Simpler and no surprises for old code.
but we could add a new feature to that: Add a new exception subclass named Info that can be used to wrap exceptions without influencing the type of the exception raised. This could be used by code higher up in the call chain to add information to the exception without changing the type that gets caught in the except statement. For example filter() could be changed to add information about the iteration index where the exception happened:
class spam: def __getitem__(self, index): if index==42: raise TypeError return None
x = filter(None, spam())
this might give:
Traceback (most recent call last): File "spam.py", line 8, in ? x = filter(None, foo()) File "spam.py", line 4, in __getitem__ raise TypeError("ouch") TypeError: ouch Info: in filter() at index 42
So have a function that takes the current exception, stores it as an attribute of a new one, and have exception-handling code no of the possible existence of the attribute and print out the info if it exists? -Brett
Brett C. wrote:
Walter Dörwald wrote:
[...]
but we could add a new feature to that: Add a new exception subclass named Info that can be used to wrap exceptions without influencing the type of the exception raised. This could be used by code higher up in the call chain to add information to the exception without changing the type that gets caught in the except statement. For example filter() could be changed to add information about the iteration index where the exception happened:
class spam: def __getitem__(self, index): if index==42: raise TypeError return None
x = filter(None, spam())
this might give:
Traceback (most recent call last): File "spam.py", line 8, in ? x = filter(None, foo()) File "spam.py", line 4, in __getitem__ raise TypeError("ouch") TypeError: ouch Info: in filter() at index 42
So have a function that takes the current exception, stores it as an attribute of a new one,
This could be done automatically, i.e. whenever you call PyErr_SetString() etc. the currently active exception will be normalized and put into a fourth global variable (exc_cause). In Python code whenever a exception handler raises a new exception the exception that is currently handled could be set as the cause for this exception automatically by the raise statement.
and have exception-handling code no of the possible existence of the attribute and print out the info if it exists?
I'd say, the attribute should always be there, but should be initialized to None in the Exception constructor (they same should probably be done for the traceback attribute). Bye, Walter Dörwald
This could be done automatically, i.e. whenever you call PyErr_SetString() etc. the currently active exception will be normalized and put into a fourth global variable (exc_cause). In Python code whenever a exception handler raises a new exception the exception that is currently handled could be set as the cause for this exception automatically by the raise statement.
More globals of course defeat the purpose (one of the reasons for putting the traceback in the exception is to get rid of sys.exc_traceback). I also think that doing this automatically whenever PyErr_Set*() is called would cause a lot of spurious tracebacks. (Unless the idea is to skip the chaining if the original exception has an empty traceback; that will almost always be the case for exceptions raised at the C level.) I worry about backwards compatibility. --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido:
More globals of course defeat the purpose (one of the reasons for putting the traceback in the exception is to get rid of sys.exc_traceback).
I think the idea was that this would be a C-level global, not a Python one (i.e. part of the existing group of C variables representing the current exception state).
I also think that doing this automatically whenever PyErr_Set*() is called would cause a lot of spurious tracebacks. (Unless the idea is to skip the chaining if the original exception has an empty traceback
I don't understand that. What is a "spurious" traceback? And how are you going to get one if the current traceback is empty?
I worry about backwards compatibility.
What would this break? Code which doesn't know about chained exceptions can just ignore the new attribute and get exactly the information they used to get from the exception and its traceback, as far as I can see. Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
Greg Ewing <greg@cosc.canterbury.ac.nz> writes:
Guido:
More globals of course defeat the purpose (one of the reasons for putting the traceback in the exception is to get rid of sys.exc_traceback).
I think the idea was that this would be a C-level global, not a Python one (i.e. part of the existing group of C variables representing the current exception state).
Those are fields in the thread state, not globals, IIRC. Cheers, M> -- Good? Bad? Strap him into the IETF-approved witch-dunking apparatus immediately! -- NTK now, 21/07/2000
Those are fields in the thread state, not globals, IIRC.
That's true. The point is that they're C variables, not Python variables, so they won't interfere with the goal of eliminating the sys.exc_xxx. Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
Greg Ewing wrote:
Guido:
More globals of course defeat the purpose (one of the reasons for putting the traceback in the exception is to get rid of sys.exc_traceback).
I think the idea was that this would be a C-level global, not a Python one (i.e. part of the existing group of C variables representing the current exception state).
Exactly. We'd only need this as sys.exc_cause, if we implemented exception chaining before moving the traceback into the exception. So maybe the plan should look somethink like this: 1. Deprecate string exceptions. 2. Make Exception a new-style class. 3. Require exceptions to be derived from Exception. 4. Make the traceback an attribute of the exception object. 5. Implement exception chaining (as an attribute named cause on the outer exception referencing the inner exception). 6. Add other exception attributes (e.g. KeyError has an attribute key, IndexError has an attribute index, IOError has attributes filename, errorcode etc.) Is there anything else that should go into the new exception PEP? (No, I'm not volunteering to write it. ;) Maybe it should be split into multiple PEPs?)
[...]
Bye, Walter Dörwald
On Thu, Jun 12, 2003, Walter Dörwald wrote:
So maybe the plan should look somethink like this:
1. Deprecate string exceptions.
2. Make Exception a new-style class.
3. Require exceptions to be derived from Exception.
4. Make the traceback an attribute of the exception object.
You've got point 2 too early; it needs to go after point 3 and posibly after point 4. -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ "If you don't know what your program is supposed to do, you'd better not start writing it." --Dijkstra
On Thu, 2003-06-12 at 06:44, Walter Dörwald wrote:
5. Implement exception chaining (as an attribute named cause on the outer exception referencing the inner exception).
I'm not keen on the name "cause" for the start of the exception chain. I'm not sure I have a better suggestion. Maybe "antecedent"? ;/ -Barry
Barry Warsaw wrote:
On Thu, 2003-06-12 at 06:44, Walter Dörwald wrote:
5. Implement exception chaining (as an attribute named cause on the outer exception referencing the inner exception).
I'm not keen on the name "cause" for the start of the exception chain. I'm not sure I have a better suggestion. Maybe "antecedent"? ;/
"reason"? Bye, Walter Dörwald
Walter Dörwald wrote:
Barry Warsaw wrote:
On Thu, 2003-06-12 at 06:44, Walter Dörwald wrote:
5. Implement exception chaining (as an attribute named cause on the outer exception referencing the inner exception).
I'm not keen on the name "cause" for the start of the exception chain. I'm not sure I have a better suggestion. Maybe "antecedent"? ;/
"reason"?
Ouch, this will collide with the PEP 293 exceptions, that already have an attribute reason. Bye, Walter Dörwald
I'm not keen on the name "cause" for the start of the exception chain. I'm not sure I have a better suggestion. Maybe "antecedent"? ;/
"reason"?
That doesn't seem any better than "cause". Maybe "precursor"? Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
On Fri, 13 Jun 2003, Greg Ewing wrote:
I'm not keen on the name "cause" for the start of the exception chain. I'm not sure I have a better suggestion. Maybe "antecedent"? ;/
"reason"?
That doesn't seem any better than "cause". Maybe "precursor"?
+1 -- Ken klm@zope.com
Barry Warsaw writes:
I'm not keen on the name "cause" for the start of the exception chain. I'm not sure I have a better suggestion. Maybe "antecedent"? ;/
I actually like "cause" better than "antecedent", though not by a whole lot. The SAX exception (SAXException, of course;) provides a method getException() to retrieve the embedded exception, though I'd prefer a simple attribute or property. -Fred -- Fred L. Drake, Jr. <fdrake at acm.org> PythonLabs at Zope Corporation
On Thu, 2003-06-12 at 08:49, Fred L. Drake, Jr. wrote:
I actually like "cause" better than "antecedent", though not by a whole lot. The SAX exception (SAXException, of course;) provides a method getException() to retrieve the embedded exception, though I'd prefer a simple attribute or property.
Me too, but "cause" implies (to me) a stronger connection between the original exception and the one you've just caught. More suggestions, none great: "original", "chain", "chainedexc", "exc_chain", "excprev", "previous". -Barry
So maybe the plan should look somethink like this:
1. Deprecate string exceptions.
2. Make Exception a new-style class.
3. Require exceptions to be derived from Exception.
4. Make the traceback an attribute of the exception object.
5. Implement exception chaining (as an attribute named cause on the outer exception referencing the inner exception).
6. Add other exception attributes (e.g. KeyError has an attribute key, IndexError has an attribute index, IOError has attributes filename, errorcode etc.)
I think (1) and (3) aren't absolutely necessary -- strings and classic classes would simply not have the traceback attribute. For backwards compatibility it could still be kept separate in (the per-thread equivalent of) sys.exc_traceback, but at some point, that would be phased out and traceback reporting for deprecated exception types would be reduced -- a nice incentive for moving to new-style exceptions! (Or, for classic classes, it wouldn't be okay to store the traceback on a system attribute, e.g. __traceback__.) --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum writes:
exceptions! (Or, for classic classes, it wouldn't be okay to store the traceback on a system attribute, e.g. __traceback__.)
I don't know that I've heard you use the term "system attribute" before -- I like it! -Fred -- Fred L. Drake, Jr. <fdrake at acm.org> PythonLabs at Zope Corporation
Guido van Rossum wrote I think (1) and (3) aren't absolutely necessary -- strings and classic classes would simply not have the traceback attribute. For backwards compatibility it could still be kept separate in (the per-thread equivalent of) sys.exc_traceback,
As an aside, is it planned that sys.exc_traceback,type and value will start emitting DeprecationWarnings any time soon? I find myself stumbling over them in other people's code far too often for comfort, where they are obviously unaware that they're not thread-safe. Anthony -- Anthony Baxter <anthony@interlink.com.au> It's never too late to have a happy childhood.
As an aside, is it planned that sys.exc_traceback,type and value will start emitting DeprecationWarnings any time soon? I find myself stumbling over them in other people's code far too often for comfort, where they are obviously unaware that they're not thread-safe.
It's hard to put a deprecation warning on these, because they're just module attributes. --Guido van Rossum (home page: http://www.python.org/~guido/)
Quoth Guido van Rossum:
As an aside, is it planned that sys.exc_traceback,type and value will start emitting DeprecationWarnings any time soon? [...]
It's hard to put a deprecation warning on these, because they're just module attributes.
This came up a day or two ago in c.l.py too. Bernhard Herzog suggested: What you could do, I think, is turn sys into an instance of a subclass of module and make exc_traceback and friends properties in that new subclass whose get functions simply return the appropriate value from sys.exc_info(). That would actually solve the bug wrt. threading and the get function could also issue a warning. [1] Seems feasible; but also seems to incur a cost for every attribute lookup in sys, and might be a bad precedent for fancy attribute access for modules. [1] <http://groups.google.com/groups?selm=6qn0gp23kr.fsf%40salmakis.intevation.de> -- Steven Taschuk Aral: "Confusion to the enemy, boy." staschuk@telusplanet.net Mark: "Turn-about is fair play, sir." -- _Mirror Dance_, Lois McMaster Bujold
As an aside, is it planned that sys.exc_traceback,type and value will start emitting DeprecationWarnings any time soon? [...]
It's hard to put a deprecation warning on these, because they're just module attributes.
This came up a day or two ago in c.l.py too. Bernhard Herzog suggested:
What you could do, I think, is turn sys into an instance of a subclass of module and make exc_traceback and friends properties in that new subclass whose get functions simply return the appropriate value from sys.exc_info(). That would actually solve the bug wrt. threading and the get function could also issue a warning. [1]
Seems feasible; but also seems to incur a cost for every attribute lookup in sys, and might be a bad precedent for fancy attribute access for modules.
[1] <http://groups.google.com/groups?selm=6qn0gp23kr.fsf%40salmakis.intevation.de>
Well, this *is* the recommended trick when you absolutely, really need to trap module attribute access. I don't expect access to sys attributes to be time-critical, with a possible exception for sys.stdout (which is used internally by the print statement). But I think attribute access, even with a warnings check, can be fast enough. The big problem is that it would require a major rewrite of the sys module, wouldn't it? --Guido van Rossum (home page: http://www.python.org/~guido/)
At 01:37 PM 6/12/03 -0400, Guido van Rossum wrote:
The big problem is that it would require a major rewrite of the sys module, wouldn't it?
Under 2.2 this would be easy because you could just do 'sys.__class__ = MyNewSysClass'. Can you still do that in 2.3 as long as 'MyNewSysClass' is a non-heap type with a compatible layout?
"Phillip J. Eby" <pje@telecommunity.com> writes:
At 01:37 PM 6/12/03 -0400, Guido van Rossum wrote:
The big problem is that it would require a major rewrite of the sys module, wouldn't it?
Under 2.2 this would be easy because you could just do 'sys.__class__ = MyNewSysClass'. Can you still do that in 2.3 as long as 'MyNewSysClass' is a non-heap type with a compatible layout?
No. Cheers, M. -- The gripping hand is really that there are morons everywhere, it's just that the Americon morons are funnier than average. -- Pim van Riezen, alt.sysadmin.recovery
The big problem is that it would require a major rewrite of the sys module, wouldn't it?
Under 2.2 this would be easy because you could just do 'sys.__class__ = MyNewSysClass'. Can you still do that in 2.3 as long as 'MyNewSysClass' is a non-heap type with a compatible layout?
I very much doubt that this worked in any version of Python 2.2 or later. --Guido van Rossum (home page: http://www.python.org/~guido/)
At 02:04 PM 6/12/03 -0400, Guido van Rossum wrote:
The big problem is that it would require a major rewrite of the sys module, wouldn't it?
Under 2.2 this would be easy because you could just do 'sys.__class__ = MyNewSysClass'. Can you still do that in 2.3 as long as 'MyNewSysClass' is a non-heap type with a compatible layout?
I very much doubt that this worked in any version of Python 2.2 or later.
Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32 Type "copyright", "credits" or "license" for more information. IDLE 0.8 -- press F1 for help
from types import ModuleType import sys class NewSys(ModuleType): __slots__ = () def exc_type(self): return self.__dict__['exc_type'] exc_type = property(exc_type)
sys.__class__ = NewSys try: raise TypeError except: print sys.exc_type
exceptions.TypeError
sys.exc_type = 1 Traceback (most recent call last): File "<pyshell#33>", line 1, in ? sys.exc_type = 1 AttributeError: can't set attribute sys.__class__ = ModuleType sys.exc_type = 1
The big problem is that it would require a major rewrite of the sys module, wouldn't it?
Under 2.2 this would be easy because you could just do 'sys.__class__ = MyNewSysClass'. Can you still do that in 2.3 as long as 'MyNewSysClass' is a non-heap type with a compatible layout?
I very much doubt that this worked in any version of Python 2.2 or later.
Python 2.2.2 (#37, Oct 14 2002, 17:02:34) [MSC 32 bit (Intel)] on win32 Type "copyright", "credits" or "license" for more information. IDLE 0.8 -- press F1 for help
from types import ModuleType import sys class NewSys(ModuleType): __slots__ = () def exc_type(self): return self.__dict__['exc_type'] exc_type = property(exc_type)
sys.__class__ = NewSys try: raise TypeError except: print sys.exc_type
exceptions.TypeError
sys.exc_type = 1 Traceback (most recent call last): File "<pyshell#33>", line 1, in ? sys.exc_type = 1 AttributeError: can't set attribute sys.__class__ = ModuleType sys.exc_type = 1
OK, so it worked. It doesn't work in 2.3. But something else might work. --Guido van Rossum (home page: http://www.python.org/~guido/)
At 02:22 PM 6/12/03 -0400, Guido van Rossum wrote:
OK, so it worked. It doesn't work in 2.3. But something else might work.
My question was whether it would work with a *C* subclass of ModuleType. In which case, presumably C code could set the type after initializing the sys module.
OK, so it worked. It doesn't work in 2.3. But something else might work.
My question was whether it would work with a *C* subclass of ModuleType. In which case, presumably C code could set the type after initializing the sys module.
Right, this could work (even though in 2.3, the module type is no longer subclassable). --Guido van Rossum (home page: http://www.python.org/~guido/)
Right, this could work (even though in 2.3, the module type is no longer subclassable).
Oh, no! Why not? There'd better be a REALLY good reason for this, because you've just killed one of the ideas I was looking forward to trying out. Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
At 12:53 PM 6/13/03 +1200, Greg Ewing wrote:
Right, this could work (even though in 2.3, the module type is no longer subclassable).
Oh, no! Why not? There'd better be a REALLY good reason for this, because you've just killed one of the ideas I was looking forward to trying out.
Don't panic. It's still subclassable as of 2.3b1. It's *modules* that you can't subclass.
"Phillip J. Eby" <pje@telecommunity.com>:
Don't panic. It's still subclassable as of 2.3b1. It's *modules* that you can't subclass.
I'm very relieved to hear that, thanks! Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
Guido van Rossum <guido@python.org> writes:
What you could do, I think, is turn sys into an instance of a subclass of module and make exc_traceback and friends properties in that new subclass whose get functions simply return the appropriate value from sys.exc_info(). That would actually solve the bug wrt. threading and the get function could also issue a warning. [1]
Seems feasible; but also seems to incur a cost for every attribute lookup in sys,
Only for those that are implemented as properties, I think.
and might be a bad precedent for fancy attribute access for modules.
Well, some of us would actually like to have this sometimes :) [...]
The big problem is that it would require a major rewrite of the sys module, wouldn't it?
It would also mean that type(sys) is no longer ModuleType, right? There is some code in the standard library that relies on this, even a few test cases. The library could easily be fixed, but chances are others also rely on this. Bernhard -- Intevation GmbH http://intevation.de/ Sketch http://sketch.sourceforge.net/ MapIt! http://www.mapit.de/
Guido van Rossum wrote:
As an aside, is it planned that sys.exc_traceback,type and value will start emitting DeprecationWarnings any time soon? [...]
It's hard to put a deprecation warning on these, because they're just module attributes.
This came up a day or two ago in c.l.py too. Bernhard Herzog suggested:
...
Well, this *is* the recommended trick when you absolutely, really need to trap module attribute access. I don't expect access to sys attributes to be time-critical, with a possible exception for sys.stdout (which is used internally by the print statement). But I think attribute access, even with a warnings check, can be fast enough.
I looked into the execution path of PyObject_GenericGetAttr. This first finds the type dictionary and sees if it can find something there. So access to special objects appears to be quite fast. The drawback is that only after searching all of the mro dicts, _PyType_Lookup gives up, and then the instance dict is inspected.
The big problem is that it would require a major rewrite of the sys module, wouldn't it?
I used a derived module class for my stackless module as well, just in order to define a couple of extra atributes, not aware of the extra costs for this. This is of course not so cheap, and with the current implementation, only the special attributes of sys would become rather cheap, which would in fact involve some work to do, because most probably most of the sys attributes might be considered special. Maybe, assuming that only very few sys attributes should grow special treatment, a special getattro() would make sense that looks into the instance(module) dict, first? Some half-baked thoughts: From another POV, modules are always just singletons, nobody really wants to create a new module type. Instead, they want a module with special attributes, which is a singleton instance. I think that after module creation, the class is no longer needed so much, since a module is created once. In a way, I think one would not want to create instances at all, but to let this single type act as class and instance at the same time. In practice, this could mean that a module is like a new type, which slot definitions, which define slots in the same object, plus the extra dictionary for ordinary module citizens. The type "module" becomes a metatype. The new modules become types which cannot create instances, but which carry both slot definitions and slots. just a rough idea -- chris -- Christian Tismer :^) <mailto:tismer@tismer.com> Mission Impossible 5oftware : Have a break! Take a ride on Python's Johannes-Niemeyer-Weg 9a : *Starship* http://starship.python.net/ 14109 Berlin : PGP key -> http://wwwkeys.pgp.net/ work +49 30 89 09 53 34 home +49 30 802 86 56 pager +49 173 24 18 776 PGP 0x57F3BF04 9064 F4E1 D754 C2FF 1619 305B C09C 5A3B 57F3 BF04 whom do you want to sponsor today? http://www.stackless.com/
On Thu, Jun 12, 2003, Christian Tismer wrote:
I looked into the execution path of PyObject_GenericGetAttr. This first finds the type dictionary and sees if it can find something there. So access to special objects appears to be quite fast. The drawback is that only after searching all of the mro dicts, _PyType_Lookup gives up, and then the instance dict is inspected.
Yes. Ping, Guido, and I were working on a patch for this, but stalled when our solution generated slower results for attributes in the most immediate base class. -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ "If you don't know what your program is supposed to do, you'd better not start writing it." --Dijkstra
More globals of course defeat the purpose (one of the reasons for putting the traceback in the exception is to get rid of sys.exc_traceback).
I think the idea was that this would be a C-level global, not a Python one (i.e. part of the existing group of C variables representing the current exception state).
Possibly, except those aren't globals either (they're members of the per-thread state record).
I also think that doing this automatically whenever PyErr_Set*() is called would cause a lot of spurious tracebacks. (Unless the idea is to skip the chaining if the original exception has an empty traceback
I don't understand that. What is a "spurious" traceback? And how are you going to get one if the current traceback is empty?
I was imagining that the default mechanism for printing tracebacks would always try to follow the chain of tracebacks, and report not just the traceback, but also the exception that was replaced. There's a lot of C code out there that catches e.g. AttributeError and replaces it with a more specific error (e.g. BifurcationError("can't bifurcate the sploorg") replacing AttributeError("__bifurcate__"). I think this would cause end user confusion.
I worry about backwards compatibility.
What would this break? Code which doesn't know about chained exceptions can just ignore the new attribute and get exactly the information they used to get from the exception and its traceback, as far as I can see.
I didn't mean code breakage, but the above change in output. --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum wrote:
[...]
I don't understand that. What is a "spurious" traceback? And how are you going to get one if the current traceback is empty?
I was imagining that the default mechanism for printing tracebacks would always try to follow the chain of tracebacks, and report not just the traceback, but also the exception that was replaced. There's a lot of C code out there that catches e.g. AttributeError and replaces it with a more specific error (e.g. BifurcationError("can't bifurcate the sploorg") replacing AttributeError("__bifurcate__"). I think this would cause end user confusion.
Isn't the new sys.exc_clear() usable for that? (I.e. raising a fresh exception without any chained ones?)
[...]
Bye, Walter Dörwald
[...]
I don't understand that. What is a "spurious" traceback? And how are you going to get one if the current traceback is empty?
I was imagining that the default mechanism for printing tracebacks would always try to follow the chain of tracebacks, and report not just the traceback, but also the exception that was replaced. There's a lot of C code out there that catches e.g. AttributeError and replaces it with a more specific error (e.g. BifurcationError("can't bifurcate the sploorg") replacing AttributeError("__bifurcate__"). I think this would cause end user confusion.
Isn't the new sys.exc_clear() usable for that? (I.e. raising a fresh exception without any chained ones?)
But that's backwards incompatible, in the sense that currently you don't need to call exc_clear() unless under very special circumstances. --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido:
There's a lot of C code out there that catches e.g. AttributeError and replaces it with a more specific error (e.g. BifurcationError("can't bifurcate the sploorg") replacing AttributeError("__bifurcate__"). I think this would cause end user confusion.
But that is a different case. As I understand it, chaining would only occur if a second exception was raised *before* the current exception was caught -- e.g. if there's a bug in a piece of code in a finally block that's being executed while unwinding to find an exception handler. In the case you're talking about, the AttributeError has been caught by the time the BifurcationError is raised, so there would be no chaining, and thus the traceback output would be the same regardless of whether chained tracebacks were printed or not. As for whether chained tracebacks should be printed when they occur, I'll have to think about that. If they are, probably the one for the most recently raised exception should be printed last, since one tends to look at the bottom of the traceback first to find the cause of the immediate problem (I do, at least). Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
There's a lot of C code out there that catches e.g. AttributeError and replaces it with a more specific error (e.g. BifurcationError("can't bifurcate the sploorg") replacing AttributeError("__bifurcate__"). I think this would cause end user confusion.
But that is a different case. As I understand it, chaining would only occur if a second exception was raised *before* the current exception was caught -- e.g. if there's a bug in a piece of code in a finally block that's being executed while unwinding to find an exception handler.
Interesting.. I had never even thought of this case. I thought chaining was specifically when catching an exception and raising another in its place. To the people who came up with the idea, which is it? (I can see an argument for both cases; maybe they should be supported using different system attributes on the exception object?) --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido:
Interesting.. I had never even thought of this case. I thought chaining was specifically when catching an exception and raising another in its place.
(I can see an argument for both cases; maybe they should be supported using different system attributes on the exception object?)
If you're explicitly catching and replacing an exception, and you want chaining, you can do it yourself. System support is really only needed for the cases where you can't do it yourself. Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
Guido van Rossum wrote:
There's a lot of C code out there that catches e.g. AttributeError and replaces it with a more specific error (e.g. BifurcationError("can't bifurcate the sploorg") replacing AttributeError("__bifurcate__"). I think this would cause end user confusion.
But that is a different case. As I understand it, chaining would only occur if a second exception was raised *before* the current exception was caught -- e.g. if there's a bug in a piece of code in a finally block that's being executed while unwinding to find an exception handler.
Interesting.. I had never even thought of this case. I thought chaining was specifically when catching an exception and raising another in its place.
To the people who came up with the idea, which is it?
I only though about the the case, where one exception is has already been raised is replaced with another exception. Exceptions in a finally clause is an interesting new scenario.
(I can see an argument for both cases; maybe they should be supported using different system attributes on the exception object?)
Sounds reasonable. If we don't want the exception replacement case to chain the exceptions automatically, we'd need this argument/attribute in all exception constructors. For the finally cause the attribute should be set by the exception machinery. Bye, Walter Dörwald
On Thu, 2003-06-12 at 20:52, Guido van Rossum wrote:
But that is a different case. As I understand it, chaining would only occur if a second exception was raised *before* the current exception was caught -- e.g. if there's a bug in a piece of code in a finally block that's being executed while unwinding to find an exception handler.
Interesting.. I had never even thought of this case. I thought chaining was specifically when catching an exception and raising another in its place.
To the people who came up with the idea, which is it?
I don't know if I participated in the earlier email discussions. I do remember some conversations in the office here. I'm interested in chaining to convert one kind of exception to another. I was debugging a case that is illustrated by the example below.
class Foo: ... pass ... {}.update(Foo()) Traceback (most recent call last): File "<stdin>", line 1, in ? AttributeError: keys
I expected a TypeError in this case, because I've passed an object to dict.update that couldn't possibly work. I looked at changing the code to generated a TypeError, but I realized that the AttributeError keys is a lot more helpful for a developer who wants to understand what went wrong. I think chained exceptions could make this error message a bit clearer. The AttributeError could become an attribute (previous?) of the TypeError that is ultimately raised. I think there are relatively few places where chaining exceptions makes sense, so I'd like to see an explicit API for chaining. Code that wants to create chained exceptions would explicitly opt in. Jeremy
It was brought up once that raising an exception after another exception was already raised ... causes the original exception to be ignored. It was suggested to keep a reference to the previous exception in the current exception
Ah, I see, thanks. Also while we're at it, how about storing the traceback in the exception object, and getting rid of sys.exc_info() etc.? Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
Also while we're at it, how about storing the traceback in the exception object, and getting rid of sys.exc_info() etc.?
That's a good idea, and I'd support a PEP on that topic more than PEP 317 (which IMO is unnecessary). --Guido van Rossum (home page: http://www.python.org/~guido/)
Quoth Guido van Rossum: [...]
That's a good idea, and I'd support a PEP on that topic more than PEP 317 (which IMO is unnecessary).
I agree it's unnecessary; even the bit about eliminating string exceptions is unnecessary. But I thought the important question was whether the proposal represents a net improvement to the language and can be achieved with acceptable migration pain. Raymond's arguing the "excessive migration pain" angle quite well, and if the PEP is to be accepted, I'll certainly have to make a more convincing counter-argument on this point than I have so far. I haven't seen any claim that it's a net worsening of the language, though some feel the improvement is negligible. (I don't think I can change their minds if the PEP's existing motivation text doesn't.) But merely being unnecessary seems a weak criterion for rejection. -- Steven Taschuk "[W]e must be very careful when we give advice staschuk@telusplanet.net to younger people: sometimes they follow it!" -- "The Humble Programmer", Edsger Dijkstra
Steven Taschuk writes:
But merely being unnecessary seems a weak criterion for rejection.
Being unnecessary while inflicting pain, however, is a good reason for rejection. It means people have to change code without giving them anything. That's bad. -Fred -- Fred L. Drake, Jr. <fdrake at acm.org> PythonLabs at Zope Corporation
Guido van Rossum: [...]
That's a good idea, and I'd support a PEP on that topic more than PEP 317 (which IMO is unnecessary).
[Steven T]
I agree it's unnecessary; even the bit about eliminating string exceptions is unnecessary. But I thought the important question was whether the proposal represents a net improvement to the language and can be achieved with acceptable migration pain.
Raymond's arguing the "excessive migration pain" angle quite well, and if the PEP is to be accepted, I'll certainly have to make a more convincing counter-argument on this point than I have so far.
I've never considered the two alternative raise syntaxes as a wart in the language that's important enough to fix. The predicted migration pain seems excessive compared to the importance of the improvement. The only case I'm willing to impose excessive migration pain to fix a problem is when the problem is *really* unacceptable in the long run. I've decided that's the case for int division, for the difference between int and long, and for new-style vs. classic classes. I don't see raise C vs. raise C() to be in the same category. --Guido van Rossum (home page: http://www.python.org/~guido/)
Quoth Guido van Rossum: [...]
I've never considered the two alternative raise syntaxes as a wart in the language that's important enough to fix. The predicted migration pain seems excessive compared to the importance of the improvement.
Gotcha. And, in case there's any doubt, I certainly agree that such an objection is more than adequate reason to reject a PEP, and that I haven't adequately met the objection (yet... he said hopefully).
The only case I'm willing to impose excessive migration pain to fix a problem is when the problem is *really* unacceptable in the long run. I've decided that's the case for int division, for the difference between int and long, and for new-style vs. classic classes.
I don't see raise C vs. raise C() to be in the same category.
I entirely agree that it isn't. -- Steven Taschuk staschuk@telusplanet.net "Telekinesis would be worth patenting." -- James Gleick
Quoth Brett C.: [...]
I am +1 on deprecating string exceptions for Python 3.
PEP 317 actually proposes formally deprecating them in 2.4, and eliminating them entirely in 3.0. Are you +1 on that? -- Steven Taschuk staschuk@telusplanet.net "Our analysis begins with two outrageous benchmarks." -- "Implementation strategies for continuations", Clinger et al.
On Mon, Jun 09, 2003, Steven Taschuk wrote:
Quoth Brett C.:
I am +1 on deprecating string exceptions for Python 3.
PEP 317 actually proposes formally deprecating them in 2.4, and eliminating them entirely in 3.0. Are you +1 on that?
Given how deeply embedded string exceptions are in Python, I believe that we cannot afford to issue a DeprecationWarning until we start doing the same for integer division. -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ "If you don't know what your program is supposed to do, you'd better not start writing it." --Dijkstra
Aahz <aahz@pythoncraft.com> writes:
On Mon, Jun 09, 2003, Steven Taschuk wrote:
Quoth Brett C.:
I am +1 on deprecating string exceptions for Python 3.
PEP 317 actually proposes formally deprecating them in 2.4, and eliminating them entirely in 3.0. Are you +1 on that?
Given how deeply embedded string exceptions are in Python,
How deep is that? 'python -X' went away, causing no pain at all as far as I could tell.
I believe that we cannot afford to issue a DeprecationWarning until we start doing the same for integer division.
$ python -E -Wall Python 2.3b1+ (#1, May 6 2003, 18:00:11) [GCC 2.96 20000731 (Red Hat Linux 7.2 2.96-112.7.2)] on linux2 Type "help", "copyright", "credits" or "license" for more information.
raise "hello" __main__:1: PendingDeprecationWarning: raising a string exception is deprecated Traceback (most recent call last): File "<stdin>", line 1, in ? hello
We don't seem to do that for integer division yet. Cheers, M. -- incidentally, asking why things are "left out of the language" is a good sign that the asker is fairly clueless. -- Erik Naggum, comp.lang.lisp
On Mon, Jun 09, 2003, Michael Hudson wrote:
Aahz <aahz@pythoncraft.com> writes:
On Mon, Jun 09, 2003, Steven Taschuk wrote:
Quoth Brett C.:
I am +1 on deprecating string exceptions for Python 3.
PEP 317 actually proposes formally deprecating them in 2.4, and eliminating them entirely in 3.0. Are you +1 on that?
Given how deeply embedded string exceptions are in Python,
How deep is that? 'python -X' went away, causing no pain at all as far as I could tell.
Well, I was still casually using string exceptions up until about a year ago, and I think I'm not the only one. There's probably lots of pre-2.0 code still running in the wild with string exceptions.
I believe that we cannot afford to issue a DeprecationWarning until we start doing the same for integer division.
$ python -E -Wall Python 2.3b1+ (#1, May 6 2003, 18:00:11) [GCC 2.96 20000731 (Red Hat Linux 7.2 2.96-112.7.2)] on linux2 Type "help", "copyright", "credits" or "license" for more information.
raise "hello" __main__:1: PendingDeprecationWarning: raising a string exception is deprecated Traceback (most recent call last): File "<stdin>", line 1, in ? hello
We don't seem to do that for integer division yet.
Correct. Note that I said "Deprecation", not "PendingDeprecation". If we're just going to use PendingDeprecation, I'm fine with that in 2.4. Seems to me that both integers and string exceptions require line-by-line analysis to correct, and I think it's unfair to shove people to do that work twice. -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ "If you don't know what your program is supposed to do, you'd better not start writing it." --Dijkstra
Well, I was still casually using string exceptions up until about a year ago, and I think I'm not the only one. There's probably lots of pre-2.0 code still running in the wild with string exceptions.
Note "casually", probably in throw-away code. If you knew they didn't exist, you'd "casually" use some built-in exception, e.g. RuntimeError. --Guido van Rossum (home page: http://www.python.org/~guido/)
Well, I was still casually using string exceptions up until about a year
ago, and I think I'm not the only one. There's probably lots of pre-2.0 code still running in the wild with string exceptions.
Note "casually", probably in throw-away code. If you knew they didn't exist, you'd "casually" use some built-in exception, e.g. RuntimeError.
I'm mostly with Guido on this however... I would venture that many of these "wild" string raises are shortcut error messages. Is there really a lot of code that does < try: catch "foo": > ? I still "casually" use string exceptions mostly as a shortcut to get unfinished code to bomb (or to generate a quick traceback. Often of the form if foo.is_simple(): foo.easy() else: raise 'zz' Granted, I could probably use raise NotImplementedError But that is more typing than I want for a quick line that will likely be ripped out the first time it actually triggers. Also, I sometimes trap NotImplementedError, so I want an exception that I would never try to catch (I don't think I could stomach a except "zz": line in my code :-). The good news for me (and I suspect many other casual string throwers) is that if < raise "zz" > raises ANY runtime exception, most of my code will continue to "do the right thing." Pat -- Patrick Miller | (925) 423-0309 | http://www.llnl.gov/CASC/people/pmiller Be the change you want to see in the world. -- Mahatma Gandhi (1869-1948)
Pat Miller <patmiller@llnl.gov>:
I still "casually" use string exceptions mostly as a shortcut to get unfinished code to bomb (or to generate a quick traceback.
raise 'zz'
You could use assert 0, 'zz' instead. Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
I am +1 on deprecating string exceptions for Python 3.
Python 3 will not have string exceptions.
PEP 317 actually proposes formally deprecating them in 2.4, and eliminating them entirely in 3.0. Are you +1 on that?
Given how deeply embedded string exceptions are in Python, I believe that we cannot afford to issue a DeprecationWarning until we start doing the same for integer division.
I don't see a reason to tie these two events together, but I agree that 2.4 is probably too early to start being noisy about string exceptions. Nevertheless they should be deprecated in all docs. --Guido van Rossum (home page: http://www.python.org/~guido/)
Quoth Raymond Hettinger: [...]
But am -1000 on eliminating implicit instantiation before Py3.0.
The proposal is, in fact, to eliminate it in 3.0, and not before. Is the PEP not clear on this point? Btw, because I expect the implicit instantiation bit to be at least somewhat controversial, I'd intended to have most of the discussion on python-list. (In fact, I just posted the PEP there, before, sadly, noticing this thread.) Should such discussion be in py-dev instead? [...]
I think it would only be fair to add:
"If this proposal is adopted, nearly every piece of non-trivial python code that has ever been written would need to be revised or would fail to run. Likewise, most tutorial and book examples would also fail."
Yes, it's a massively backwards-incompatible change. But I get the feeling I'm missing the point you're making by emphasizing the fact. Is the point that you think readers of the PEP won't understand the scope of the backwards-incompatibility, and so the point deserves more emphasis? I'd thought it was obvious. Is the point that you think it's too backwards-incompatible to be implemented as early as 3.0? If so, I'd like to hear it explicitly, and also your thoughts on what kind of schedule, if any, seems more appropriate. -- Steven Taschuk staschuk@telusplanet.net "I'm always serious, never more so than when I'm being flippant." -- _Look to Windward_, Iain M. Banks
I think it would only be fair to add:
"If this proposal is adopted, nearly every piece of non-trivial
"Raymond Hettinger" <raymond.hettinger@verizon.net> wrote in message news:001f01c32e41$b4b7c440$4827a044@oemcomputer... python
code that has ever been written would need to be revised or would fail to run. Likewise, most tutorial and book examples would also fail."
A conversion utility that converted 'raise item' to 'raise item()' and 'raise item,arg' to 'raise item(arg)' would definitely be helpful. A working version, or at least a promise to produce one on acceptance might make the PEP more palatable. Terry J. Reedy
At 09:58 09.06.2003 -0400, Terry Reedy wrote:
I think it would only be fair to add:
"If this proposal is adopted, nearly every piece of non-trivial
"Raymond Hettinger" <raymond.hettinger@verizon.net> wrote in message news:001f01c32e41$b4b7c440$4827a044@oemcomputer... python
code that has ever been written would need to be revised or would fail to run. Likewise, most tutorial and book examples would also fail."
A conversion utility that converted 'raise item' to 'raise item()' and 'raise item,arg' to 'raise item(arg)' would definitely be helpful. A working version, or at least a promise to produce one on acceptance might make the PEP more palatable.
given that in: raise X raise X,y raise X(...) (likely) in most cases X is a builtin/global constant/or comes straight from an import, such a static analysis tool should be doable, for the rest the user could be informed about non-straightforward cases like: def raise_(X,y): raise X,y regards.
At 16:27 09.06.2003 +0200, Samuele Pedroni wrote:
At 09:58 09.06.2003 -0400, Terry Reedy wrote:
I think it would only be fair to add:
"If this proposal is adopted, nearly every piece of non-trivial
"Raymond Hettinger" <raymond.hettinger@verizon.net> wrote in message news:001f01c32e41$b4b7c440$4827a044@oemcomputer... python
code that has ever been written would need to be revised or would fail to run. Likewise, most tutorial and book examples would also fail."
A conversion utility that converted 'raise item' to 'raise item()' and 'raise item,arg' to 'raise item(arg)' would definitely be helpful. A working version, or at least a promise to produce one on acceptance might make the PEP more palatable.
given that in:
raise X raise X,y raise X(...)
(likely) in most cases X is a builtin/global constant/or comes straight from an import, such a static analysis tool should be doable, for the rest the user could be informed about non-straightforward cases like:
def raise_(X,y): raise X,y
the point: such a tool could also statically detect string exceptions usage, I think PyChecker already is able of that.
On Mon, Jun 09, 2003 at 04:35:55PM +0200, Samuele Pedroni wrote:
At 16:27 09.06.2003 +0200, Samuele Pedroni wrote:
At 09:58 09.06.2003 -0400, Terry Reedy wrote:
A conversion utility that converted 'raise item' to 'raise item()' and 'raise item,arg' to 'raise item(arg)' would definitely be helpful. A working version, or at least a promise to produce one on acceptance might make the PEP more palatable.
given that in:
raise X raise X,y raise X(...)
(likely) in most cases X is a builtin/global constant/or comes straight from an import, such a static analysis tool should be doable, for the rest the user could be informed about non-straightforward cases like:
def raise_(X,y): raise X,y
the point: such a tool could also statically detect string exceptions usage, I think PyChecker already is able of that.
Yes, it does. PyChecker could be modified to check for 'raise item' vs. 'raise item()' too. I'm all for removing string exceptions, but -1 on the PEP. I don't see the benefit. It seems to require more keystrokes for at best a very small conceptual benefit. BTW, this may be more parallel to Java, but not C++. How about Ruby? Just curious... Neal
I'm worried about the proposed elimination of deferred instantiation of exceptions in Python code. The PEP asserts that this is an optimisation that should only be of interest in C code. But in Pyrex, the distinction between Python and C is blurred. Currently, if you raise an exception in Pyrex using the implicit instantiation syntax, instantiation is also deferred, and I think this is a good thing. But if the implicit instantiation syntax goes away, this will no longer be possible while keeping the same syntax for the raise statement in Python and Pyrex. It seems to me it's not necessary to eliminate implicit instantiation altogether, but only to remove the ambiguity between implicit and explicit instantiation. This could be done by mandating that raise expr *never* instantiates implicitly, whereas raise classexpr, valueexpr *always* instantiates implicitly, possibly also deferred. Specification of a traceback would be done with a new keyword, e.g. raise expr [,expr] traceback tb which I think is a good idea anyway, since it makes it a lot clearer what the currently-somewhat-obscure third argument actually is. Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
Quoth Greg Ewing:
I'm worried about the proposed elimination of deferred instantiation of exceptions in Python code. The PEP asserts that this is an optimisation that should only be of interest in C code.
Yes -- and without argument! I quite liked writing that bit. Btw, just to be clear: in pure Python, deferred instantiation is already impossible; implicit instantiation is exactly equivalent to explicit. I admit I hadn't thought of Pyrex at all. I see that the trade-offs are different there, and deferring instantiation might well make lots of sense. [...]
It seems to me it's not necessary to eliminate implicit instantiation altogether, but only to remove the ambiguity between implicit and explicit instantiation. This could be done by mandating that
raise expr
*never* instantiates implicitly, whereas
raise classexpr, valueexpr
*always* instantiates implicitly, possibly also deferred.
In this plan, in order to raise, say, a TypeError with deferred instantiation and no arguments, you'd have to write raise TypeError, () right?
Specification of a traceback would be done with a new keyword, e.g.
raise expr [,expr] traceback tb
which I think is a good idea anyway, since it makes it a lot clearer what the currently-somewhat-obscure third argument actually is.
I like that. I would also like the traceback to be an attribute of the exception object (circular references be damned!), specified by optional keyword argument to Exception.__init__. This would require that people writing their own exception classes be sure to extend, not override, Exception.__init__. -- Steven Taschuk staschuk@telusplanet.net "[T]rue greatness is when your name is like ampere, watt, and fourier -- when it's spelled with a lower case letter." -- R.W. Hamming
Steven Taschuk <staschuk@telusplanet.net>:
Btw, just to be clear: in pure Python, deferred instantiation is already impossible; implicit instantiation is exactly equivalent to explicit.
I know that's the way it *is*, but I can't see any reason why the interpreter couldn't defer instantiation if it wanted to. It should be an optimisation that any part of the implementation is free to make if the programmer hasn't explicitly instantiated before raising.
In this plan, in order to raise, say, a TypeError with deferred instantiation and no arguments, you'd have to write
raise TypeError, ()
Hmmm, yes, it would appear so. I must admit that does look a bit ugly. But something else has occurred to me. If we're going to require exception classes to be derived from Exception, then there's no ambiguity anyway, because you can't have an object which is both a subclass of Exception and an instance of a subclass of Exception. (At least not without pulling some sort of bizarre trick, and I don't much care what happens to anyone who does that.-) Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
Quoth Greg Ewing: [...]
I know that's the way it *is*, but I can't see any reason why the interpreter couldn't defer instantiation if it wanted to. It should be an optimisation that any part of the implementation is free to make if the programmer hasn't explicitly instantiated before raising.
The interpreter certainly could do that, but imho it would be a Bad Thing. Forgive my long-windedness, but: Imho, it's bad enough that raise MyError, 'foo' raise MyError('foo') are two ways of saying the same thing; that's merely confusing. But having the interpreter defer instantiation in the former case would make them a much worse pair -- two subtly different ways of saying almost the same thing, where the difference is one you almost never care about. I cringe. To be more concrete, if exception instantiation might be deferred and might not occur at all, then (off the top of my head): 1. Logging code in an exception's __init__ might be called, might not. 2. sys._getframe tricks in an exception's __init__ might work, might not. (And exceptions are just the kind of infrastructure- level thing where such tricks are most likely to be useful, imho. You might, for example, want to grab a copy of all the locals of the function which raised the exception, for error reporting. Sure you could use the traceback, if you can get ahold of it somehow, but everywhere *else* this kind of machinery uses sys._getframe, so...) 3. Implementations of __new__ in which the created object is not of the requested class would make the exception type depend on whether instantiation was deferred or not, affecting whether and when it gets caught. Perhaps these aren't showstoppers, but I really like it when optimizations are completely transparent. Besides, almost all raise statements report errors which prevent normal processing, and so have no use for such an optimization anyway. And even when using exceptions for control flow on performance- critical paths, you can avoid paying the instantiation cost in inner loops by other, simpler, means -- e.g., create one instance of your FancyControlFlow exception up front and raise that one object as needed. There's also some (surmountable) implementation issues: Suppose we enter an except block without instantiating the exception; what are the values of sys.exc_type etc. then? Are they possibly denormalized? Or do we remove sys.exc_{type, value, traceback} entirely, and have calling sys.exc_info() cause instantiation? If explicit instantiation were standard, and the implicit instantiation syntax were now being proposed with deferred-and- skipped-if-possible semantics, I might just be -0 YAGNI on it. In that scenario, this syntax would be something weird that programmers would only use if they knew they needed it. But the actual circumstance is, to judge by the stdlib, that implicit instantiation is today the de facto standard way to raise an exception. Thus adding such semantics now would give the normal form weird behaviour to enable an optimization which is useful only in specialized circumstances -- which puts me firmly in the -1 AAAGH! camp. All of the above is intended for pure Python only. If the tradeoffs are much different in Pyrex, I'd like to hear more details. [...]
But something else has occurred to me. If we're going to require exception classes to be derived from Exception, then there's no ambiguity anyway, [...]
For old-style classes, there's no ambiguity now, either. But yes, requiring inheritance from Exception seems to eliminate any instance/class ambiguities for future new-style exceptions too. (It also avoids certain other problems; see Alex's persuasive arguments in c.l.py around the beginning of May, mentioned elsewhere in this thread.) PEP 317 isn't primarily concerned with that ambiguity, of course; more with the loss of clarity in present-day everyday code.
[...] because you can't have an object which is both a subclass of Exception and an instance of a subclass of Exception. (At least not without pulling some sort of bizarre trick, and I don't much care what happens to anyone who does that.-)
Couldn't agree more. -- Steven Taschuk staschuk@telusplanet.net "Its force is immeasurable. Even Computer cannot determine it." -- _Space: 1999_ episode "Black Sun"
Hi, all, I am new to Python's core. I have a question here. Is the "byte code interpreter" part implemented as a separate part, say, a dll or so? If not, why? The advantage to make interpreter a "plug-in" like module is: We can test different interpreter implementations or optimizers easily.
On Tue, Jun 10, 2003, Yan Weng wrote:
I am new to Python's core. I have a question here. Is the "byte code interpreter" part implemented as a separate part, say, a dll or so? If not, why?
The advantage to make interpreter a "plug-in" like module is: We can test different interpreter implementations or optimizers easily.
That's a complicated question; more precisely, it has a complicated answer. In a lot of ways, the byte code interpreter is the true core of Python, and it's everything else that is separate (or potentially separable). I'd sugest that you get involved with the PyPy if you're really interested in this topic. http://codespeak.net/moin/pypy/ -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ "If you don't know what your program is supposed to do, you'd better not start writing it." --Dijkstra
"Yan Weng" <yweng@cs.uoregon.edu> wrote in message news:000b01c32f24$89ac89a0$b9acdf80@uo0b0aw1s4pcg0...
I am new to Python's core. I have a question here. Is the "byte code interpreter" part implemented as a separate part, say, a dll or so? If not, why?
The advantage to make interpreter a "plug-in" like module is: We can test different interpreter implementations or optimizers easily.
I doubt that the extra time taken to link in 'everything else' (already compiled) is the major barrier to experimenting with the byte code interpreter ;-) Many such experiments involve changing the byte code itself, and hence the byte code compiler also. Terry J. Reedy PS. When you start a new topic, start a new thread instead of piggybacking on an existing thread. Thread-aware readers typically present a list of one line per thread and expand on request. If I were not reading the thread on PEP 317, I would not have seen this.
Btw, just to be clear: in pure Python, deferred instantiation is already impossible; implicit instantiation is exactly equivalent to explicit.
Almost exactly:
def f(): raise ValueError, 1
def g(): raise ValueError(1)
from dis import dis dis(f) 2 0 LOAD_GLOBAL 0 (ValueError) 3 LOAD_CONST 1 (1) 6 RAISE_VARARGS 2 9 LOAD_CONST 0 (None) 12 RETURN_VALUE dis(g) 2 0 LOAD_GLOBAL 0 (ValueError) 3 LOAD_CONST 1 (1) 6 CALL_FUNCTION 1 9 RAISE_VARARGS 1 12 LOAD_CONST 0 (None) 15 RETURN_VALUE
On a separate note, I was experimented with explicit instantiation and noticed an oddity with my editor's autocomplete. Upon typing: raise TypeError( the autocompleter looks up the doc string for TypeError and announces: Inappropriate argument type when you were likely expecting to be prompted for the exception value. Perhaps the doc string should read like this: TypeError([exceptionvalue]) --> Exception for inappropriate argument type. Raymond Hettinger
Steven Taschuk wrote:
[...] I would also like the traceback to be an attribute of the exception object (circular references be damned!), specified by optional keyword argument to Exception.__init__. This would require that people writing their own exception classes be sure to extend, not override, Exception.__init__.
Wouldn't it make more sense to associate the traceback with the exception instance when the exception is raised, not when the exception is instantiated? As long as the exception isn't raised it's just a normal object without a traceback attached. The warning framework and PEP 293 use unraised exceptions for passing around error information, it would be bad if the would gain traceback info automatically. Bye, Walter Dörwald
Quoth Walter Dörwald:
Steven Taschuk wrote:
[...] I would also like the traceback to be an attribute of the exception object (circular references be damned!), specified by optional keyword argument to Exception.__init__. [...]
Wouldn't it make more sense to associate the traceback with the exception instance when the exception is raised, not when the exception is instantiated? As long as the exception isn't raised it's just a normal object without a traceback attached.
Absolutely; my notion to use __init__ above actually makes no sense, I subsequently realized. Consider it withdrawn. -- Steven Taschuk o- @ staschuk@telusplanet.net 7O ) " (
Quoth Terry Reedy: [...]
A conversion utility that converted 'raise item' to 'raise item()' and 'raise item,arg' to 'raise item(arg)' would definitely be helpful. A working version, or at least a promise to produce one on acceptance might make the PEP more palatable.
I do intend to write such a tool. I'd imagined that, being PEP champion, I would be the obvious person to produce the relevant patches to the standard library. There are more than a thousand raise statements there, mostly of the implicitly instantiating type, so you can bet I'm not doing it by hand if I can avoid it. -- Steven Taschuk staschuk@telusplanet.net "[T]rue greatness is when your name is like ampere, watt, and fourier -- when it's spelled with a lower case letter." -- R.W. Hamming
Quoth Terry Reedy: [...]
A conversion utility that converted 'raise item' to 'raise item()' and 'raise item,arg' to 'raise item(arg)' would definitely be helpful. A working version, or at least a promise to produce one on acceptance might make the PEP more palatable.
I do intend to write such a tool.
I'd imagined that, being PEP champion, I would be the obvious person to produce the relevant patches to the standard library. There are more than a thousand raise statements there, mostly of the implicitly instantiating type, so you can bet I'm not doing it by hand if I can avoid it.
PEP-290 advises against automated tools for this type of change. Every line of code needs to be read and understood before changing it. Then, each change should be reviewed. It's the only way to make sure you're not introducing mindless cut and paste errors throughout the code. It is for this reason that I've spent more than one weekend reviewing every line of Walter's code updates -- he does them by hand and has less than a 2% error rate. Also, take a look at what would need to be done to the test suite. The changes there are less amenable to an automated update. Grep could find most potential changes but I don't see how you can statically determine whether 'raise x' is a class or instance without running the code. That brings up the question of whether the warnings are a runtime or compile time event. Can you always determine at compile time whether raise Class is being used? If not, the performance penalty for the warnings module is something else to consider. Except for conceptual purity, is there any real payoff in terms of performance or capability that would warrant a wholesale revision of working code? Raymond Hettinger ################################################################# ################################################################# ################################################################# ##### ##### ##### ################################################################# ################################################################# #################################################################
Quoth Raymond Hettinger: [...]
PEP-290 advises against automated tools for this type of change.
I certainly agree to the need for human review of such changes. I don't think this would be onerous, though (as you've suggested in private email) I should certainly try it myself. [...]
Also, take a look at what would need to be done to the test suite. The changes there are less amenable to an automated update.
I will.
Grep could find most potential changes but I don't see how you can statically determine whether 'raise x' is a class or instance without running the code.
That's true. Certain cases of two- and three- argument raise statements are difficult as well. Rather than discuss it in the abstract, how about I just implement the tool I have in mind and see how well it works? [...] -- Steven Taschuk staschuk@telusplanet.net "Tomorrow never happens." -- Janis Joplin
Quoth Raymond Hettinger: [...]
That brings up the question of whether the warnings are a runtime or compile time event. Can you always determine at compile time whether raise Class is being used? If not, the performance penalty for the warnings module is something else to consider.
As the PEP says, the warning about using three arguments is issued at compile-time, while the others are at run-time, in keeping with when the corresponding future errors would occur. The performance penalty of the warnings is a legitimate concern, but I don't expect it to be a serious problem: 1. The compile-time warning is, well, issued at compile time, which is not usually on a performance-critical path. 2. The run-time warnings are issued when raising an exception; also not usually on a performance-critical path. (Except for things like StopIteration. But the PEP does not propose any change to the C API, so the built-in iterators won't be affected.) -- Steven Taschuk staschuk@telusplanet.net Receive them ignorant; dispatch them confused. (Weschler's Teaching Motto)
Quoth Raymond Hettinger: [...]
Except for conceptual purity, is there any real payoff in terms of performance or capability that would warrant a wholesale revision of working code?
There's also the question (mentioned in the PEP, albeit parenthetically) of how implicit instantiation could work with any future plan to allow new-style exceptions. This point is also being discussed in the thread on c.l.py; shall we adjourn there? -- Steven Taschuk staschuk@telusplanet.net "I may be wrong but I'm positive." -- _Friday_, Robert A. Heinlein
At 12:54 PM 6/9/03 -0600, Steven Taschuk wrote:
Quoth Raymond Hettinger: [...]
Except for conceptual purity, is there any real payoff in terms of performance or capability that would warrant a wholesale revision of working code?
There's also the question (mentioned in the PEP, albeit parenthetically) of how implicit instantiation could work with any future plan to allow new-style exceptions.
isinstance(ob,Exception) issubclass(cls,Exception) That is, a new-style exception would have to be an instance or subclass of Exception. The *real* thing that's broken is the check to see if an exception is a tuple! isinstance(ob,Exception) should be checked first. I guess I'm missing why this wouldn't work for new-style exceptions, provided they are required to subclass Exception (which I thought everything was going to be required to do eventually).
I guess I'm missing why this wouldn't work for new-style exceptions, provided they are required to subclass Exception (which I thought everything was going to be required to do eventually).
I'm dithering on that, actually. It's a Java vs. C++ thing: in C++ you can raise any type, in Java it must be an Exception instance. Python usually doesn't care about isinstance relationships but cares about whether the needed protocol is implemented, and this suggests that requiring exceptions to subclass Exception is unPythonic. But at other times, the desire to catch bogus arguments to raise suggests that the subclass requirement might be just fine, and I don't have a use case that breaks with this requirement (since you can always use multiple inheritance to make a desirable class raisable). --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum writes:
Python usually doesn't care about isinstance relationships but cares about whether the needed protocol is implemented, and this suggests that requiring exceptions to subclass Exception is unPythonic.
Definiately!
But at other times, the desire to catch bogus arguments to raise suggests that the subclass requirement might be just fine, and I don't have a use case that breaks with this requirement (since you can always use multiple inheritance to make a desirable class raisable).
Yeah, but that's really annoying. -Fred -- Fred L. Drake, Jr. <fdrake at acm.org> PythonLabs at Zope Corporation
At 03:03 PM 6/9/03 -0400, Guido van Rossum wrote:
I guess I'm missing why this wouldn't work for new-style exceptions, provided they are required to subclass Exception (which I thought everything was going to be required to do eventually).
I'm dithering on that, actually. It's a Java vs. C++ thing: in C++ you can raise any type, in Java it must be an Exception instance.
Python usually doesn't care about isinstance relationships but cares about whether the needed protocol is implemented, and this suggests that requiring exceptions to subclass Exception is unPythonic.
Hm. I suppose if we had PEP 246 in the core, we could always 'adapt(ob,Exception)' instead, and also define an adaptation for tuples to become exceptions. ;)
But at other times, the desire to catch bogus arguments to raise suggests that the subclass requirement might be just fine, and I don't have a use case that breaks with this requirement (since you can always use multiple inheritance to make a desirable class raisable).
And I expect that even Jim Fulton won't argue that a subclass of an Exception subclass should be able to change its stripes and *not* be usable as an Exception any more. In other words, I don't think it's any more of a wart than requiring someone to subclass datetime.tzinfo.
Quoth Guido van Rossum: [...]
Python usually doesn't care about isinstance relationships but cares about whether the needed protocol is implemented, and this suggests that requiring exceptions to subclass Exception is unPythonic.
This came up in python-list not long ago [1], and I raised (heh) exactly that argument. Alex Martelli counterargued that exceptions are one area in which we *do* usually care about isinstance relationships, since that's how we specify which exceptions to catch. [1] http://mail.python.org/pipermail/python-list/2003-May/160965.html -- Steven Taschuk staschuk@telusplanet.net "I'm always serious, never more so than when I'm being flippant." -- _Look to Windward_, Iain M. Banks
Quoth Guido van Rossum: [...]
Python usually doesn't care about isinstance relationships but cares about whether the needed protocol is implemented, and this suggests that requiring exceptions to subclass Exception is unPythonic.
[Steven T]
This came up in python-list not long ago [1], and I raised (heh) exactly that argument. Alex Martelli counterargued that exceptions are one area in which we *do* usually care about isinstance relationships, since that's how we specify which exceptions to catch.
[1] http://mail.python.org/pipermail/python-list/2003-May/160965.html
Excellent argument. Thanks, Steve and Alex. --Guido van Rossum (home page: http://www.python.org/~guido/)
Steven Taschuk writes:
This came up in python-list not long ago [1], and I raised (heh) exactly that argument. Alex Martelli counterargued that exceptions are one area in which we *do* usually care about isinstance relationships, since that's how we specify which exceptions to catch.
This is a good point. So I'll find it annoying, but it does make sense, so I'll get over it (eventually). -Fred -- Fred L. Drake, Jr. <fdrake at acm.org> PythonLabs at Zope Corporation
I don't have a use case that breaks with this requirement (since you can always use multiple inheritance to make a desirable class raisable).
What if the desirable class has a C layout that conflicts with that of Exception? Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
At 10:48 AM 6/10/03 +1200, Greg Ewing wrote:
I don't have a use case that breaks with this requirement (since you can always use multiple inheritance to make a desirable class raisable).
What if the desirable class has a C layout that conflicts with that of Exception?
Can't Exception be "abstract" with respect to layout?
"Phillip J. Eby" <pje@telecommunity.com> writes:
At 10:48 AM 6/10/03 +1200, Greg Ewing wrote:
I don't have a use case that breaks with this requirement (since you can always use multiple inheritance to make a desirable class raisable).
What if the desirable class has a C layout that conflicts with that of Exception?
Can't Exception be "abstract" with respect to layout?
Already is:
class EL(list, Exception): ... pass ... issubclass(EL, list) True issubclass(EL, Exception) True
Exception and its subclasses are bona-fide old-style classes. The fact that they happen to be implemented in C doesn't change that. Cheers, M. -- This is an off-the-top-of-the-head-and-not-quite-sober suggestion, so is probably technically laughable. I'll see how embarassed I feel tomorrow morning. -- Patrick Gosling, ucam.comp.misc
I don't have a use case that breaks with this requirement (since you can always use multiple inheritance to make a desirable class raisable).
What if the desirable class has a C layout that conflicts with that of Exception?
Perhaps Exception should have a null C layout? But I still call YAGNI on this use case until I hear a good reason why you'd ever want to raise a 3rd party class and it's not (a) for backwards compatibility reasons or (b) just as easy to raise another class with this class instance as an attribute. --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum <guido@python.org>:
But I still call YAGNI on this use case until I hear a good reason why you'd ever want to raise a 3rd party class and it's not (a) for backwards compatibility reasons or (b) just as easy to raise another class with this class instance as an attribute.
I'm happy with that. Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
Raymond> Grep could find most potential changes but I don't see how you Raymond> can statically determine whether 'raise x' is a class or Raymond> instance without running the code. I agree no perfect solution is possible, but I think a 90% solution is easily acheived. If what's being raised is one of the standard errors and it's not mentioned as the lhs of an assignment within the module, it's almost certain that a standard exception class is being raised. That reduces the bulk of the problem down to reviewing the automatic changes. No matter how completely you try to automate the process, any converter or raise statement locator (like "egrep -n '^[\t ]*raise ' *.py") should print lines it modifies or discovers in a form which editors like Emacs can parse, e.g.: httplib.py:247: raise BadStatusLine(line) httplib.py:257: raise BadStatusLine(line) httplib.py:259: raise BadStatusLine(line) httplib.py:289: raise UnknownProtocol(version) httplib.py:475: raise IncompleteRead(s) httplib.py:482: raise ResponseNotReady() httplib.py:515: raise InvalidURL("nonnumeric port: '%s'" % host[i+1:]) httplib.py:545: raise socket.error, msg httplib.py:563: raise NotConnected() httplib.py:630: raise CannotSendRequest() httplib.py:697: raise CannotSendHeader() httplib.py:708: raise CannotSendHeader() httplib.py:767: raise ResponseNotReady() httplib.py:915: raise error(9, 'Bad file descriptor') httplib.py:928: raise UnimplementedFileMode() This makes it a lot easier to work your way through the lines which need attention. (Before people accuse me of being an Emacs bigot I readily admit that I am. Let me suggest that this magic tool take an optional format parameter which defaults to something like "%(file)s:%(line)d:%(source)s". That should allow the tool to format its output to most any text editor or ide's notions of what compiler error messages look like.) Skip
participants (23)
-
Aahz
-
Anthony Baxter
-
Barry Warsaw
-
Bernhard Herzog
-
Brett C.
-
Christian Tismer
-
Fred L. Drake, Jr.
-
Greg Ewing
-
Guido van Rossum
-
Jeremy Hylton
-
Ken Manheimer
-
Michael Hudson
-
Neal Norwitz
-
Pat Miller
-
Phillip J. Eby
-
Raymond Hettinger
-
Raymond Hettinger
-
Samuele Pedroni
-
Skip Montanaro
-
Steven Taschuk
-
Terry Reedy
-
Walter Dörwald
-
Yan Weng