[gmane.comp.python.pypy] deep breakage
![](https://secure.gravatar.com/avatar/1efc90ff6075b7654d8a8ce6e51a2cd3.jpg?s=120&d=mm&r=g)
What's going on? -- The above comment may be extremely inflamatory. For your protection, it has been rot13'd twice. -- the signature of "JWhitlock" on slashdot
![](https://secure.gravatar.com/avatar/5b37e6b4ac97453e4ba9dba37954cf79.jpg?s=120&d=mm&r=g)
Hello Michael, On Sat, Jun 07, 2003 at 08:38:32PM +0100, Michael Hudson wrote:
try: "x" + 1 except TypeError, e: raise e
because here 'e' gets bound to a *string* and then this is what's reraised.
This is the same problem as in CPython. Most failing internal operations call PyErr_SetString(), which causes a string to be used as the exception value. The hack is that when the user code reaches an 'except' clauses the exception is "normalized", which translates the pair "TypeError class + string" into the pair "TypeError class + TypeError instance". We might either choose to mimic this behavior or clean it up a bit, e.g. by always using internally a single object as the exception instance. String exceptions are being deprecated, but still we could reasonably emulate them, say by inventing a StringException class. This would isolate the hacky parts around this specific class (like setting sys.exc_type to something else than current_exception.__class__ for this particular case). A bientôt, Armin.
![](https://secure.gravatar.com/avatar/1efc90ff6075b7654d8a8ce6e51a2cd3.jpg?s=120&d=mm&r=g)
I wonder if I can post via gmane yet... Armin Rigo <arigo@tunes.org> writes:
Hello Michael,
On Sat, Jun 07, 2003 at 08:38:32PM +0100, Michael Hudson wrote:
try: "x" + 1 except TypeError, e: raise e
because here 'e' gets bound to a *string* and then this is what's reraised.
This is the same problem as in CPython. Most failing internal operations call PyErr_SetString(), which causes a string to be used as the exception value. The hack is that when the user code reaches an 'except' clauses the exception is "normalized", which translates the pair "TypeError class + string" into the pair "TypeError class + TypeError instance".
I think I now have code that does this, after modifying decode_code_arguments to not try to catch IndexError (that one was fun to find!).
We might either choose to mimic this behavior or clean it up a bit, e.g. by always using internally a single object as the exception instance.
I couldn't get normalizing the exception at raise time (roughly what you mean here, right?) to work... there may be a reason other than performance that CPython does it this way.
String exceptions are being deprecated, but still we could reasonably emulate them, say by inventing a StringException class. This would isolate the hacky parts around this specific class (like setting sys.exc_type to something else than current_exception.__class__ for this particular case).
I'm not sure I understand... Cheers, M> -- Two decades later, well-known hacker Henry Spencer described the Perl scripting language as a "Swiss-Army chainsaw", intending to convey his evaluation of the language as exceedingly powerful but ugly and noisy and prone to belch noxious fumes. -- the jargon file
![](https://secure.gravatar.com/avatar/5b37e6b4ac97453e4ba9dba37954cf79.jpg?s=120&d=mm&r=g)
Hello Michael, On Mon, Jun 09, 2003 at 10:36:08AM +0100, Michael Hudson wrote:
We might either choose to mimic this behavior or clean it up a bit, e.g. by always using internally a single object as the exception instance.
I couldn't get normalizing the exception at raise time (roughly what you mean here, right?) to work... there may be a reason other than performance that CPython does it this way.
Ah. Not sure exactly why. I am only aware of two ways CPython ever tries to set exceptions: either by the 'raise' statement, which does the normalization stuff immediately; or by one of the PyErr_SetXxx() calls, which as far as I am aware is only ever used on built-in exception types (so no user code runs as a result of normalizing these exceptions). The only reason I can see so far is MemoryError, which (if we don't normalize it right away) can be raised without memory allocation. However even this example is dubious, because we could have a pre-built MemoryError instance in a corner just in case. But well, I'm not completely aware of all the funny start-up inter-dependencies...
String exceptions are being deprecated, but still we could reasonably emulate them, say by inventing a StringException class. This would isolate the hacky parts around this specific class (like setting sys.exc_type to something else than current_exception.__class__ for this particular case).
I'm not sure I understand...
The point what just that if we replace the internal exc_type/exc_value pair with a single exc_value pointer (which is the clean thing to do in my opinion), then we cannot represent string exceptions any more and have to come up with a new class whose instances can store both the string describing the exception, and the associated value. Armin
![](https://secure.gravatar.com/avatar/1efc90ff6075b7654d8a8ce6e51a2cd3.jpg?s=120&d=mm&r=g)
Armin Rigo <arigo@tunes.org> writes:
Hello Michael,
On Mon, Jun 09, 2003 at 10:36:08AM +0100, Michael Hudson wrote:
We might either choose to mimic this behavior or clean it up a bit, e.g. by always using internally a single object as the exception instance.
I couldn't get normalizing the exception at raise time (roughly what you mean here, right?) to work... there may be a reason other than performance that CPython does it this way.
Ah. Not sure exactly why. I am only aware of two ways CPython ever tries to set exceptions: either by the 'raise' statement, which does the normalization stuff immediately; or by one of the PyErr_SetXxx() calls, which as far as I am aware is only ever used on built-in exception types (so no user code runs as a result of normalizing these exceptions). The only reason I can see so far is MemoryError, which (if we don't normalize it right away) can be raised without memory allocation. However even this example is dubious, because we could have a pre-built MemoryError instance in a corner just in case. But well, I'm not completely aware of all the funny start-up inter-dependencies...
But but but ... instantiating an Exception object involves calling a callable, which unless you're careful will involve a call to unpackiterable which depends on being able to raise IndexError ... Actually, my change to decode_code_arguments may have made this possible. I'll check, but I'm sure there are other entertaining infinite recursions lying in wait.
String exceptions are being deprecated, but still we could reasonably emulate them, say by inventing a StringException class. This would isolate the hacky parts around this specific class (like setting sys.exc_type to something else than current_exception.__class__ for this particular case).
I'm not sure I understand...
The point what just that if we replace the internal exc_type/exc_value pair with a single exc_value pointer (which is the clean thing to do in my opinion), then we cannot represent string exceptions any more and have to come up with a new class whose instances can store both the string describing the exception, and the associated value.
Oh right. I could explain how much I care about string exceptions, but with a fixed width font, all characters are too wide. Cheers, M. -- The ability to quote is a serviceable substitute for wit. -- W. Somerset Maugham
![](https://secure.gravatar.com/avatar/1efc90ff6075b7654d8a8ce6e51a2cd3.jpg?s=120&d=mm&r=g)
Michael Hudson <mwh@python.net> writes:
This is the same problem as in CPython. Most failing internal operations call PyErr_SetString(), which causes a string to be used as the exception value. The hack is that when the user code reaches an 'except' clauses the exception is "normalized", which translates the pair "TypeError class + string" into the pair "TypeError class + TypeError instance".
I think I now have code that does this, after modifying decode_code_arguments to not try to catch IndexError (that one was fun to find!).
I've checked my code in. I'm not totally certain of it, but I was able to reenable a few tests of the exception machinery in test_interpreter.py, so I'm going to pronounce it "good enough for now". Incidentally, on this machine Plain Old Python does something like 5-6000 pystones a sec PyPy/TrivialObjSpace does ~ 7 PyPy/StdObjSpace does ~ 0.2 (this is in the battery-saving reduced processor performance mode, & with some hacks to let pyston import time.clock) Cheers, M. -- Worryingly, DEFUN appears to be a function that removes all the fun from something: after using it all your code is converted to C++. -- Tim Bradshaw, comp.lang.lisp
participants (2)
-
Armin Rigo
-
Michael Hudson