471,350 Members | 1,650 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,350 software developers and data experts.

Instance Exception Oddity: Implicit and Explicit not the same?

>>> class E1(Exception): pass
class E2(E1): pass i = E2('foo')
raise E1(i) Traceback (most recent call last):
File "<pyshell#5>", line 1, in ?
raise E1(i)
E1: foo raise E1, i Traceback (most recent call last):
File "<pyshell#6>", line 1, in ?
raise E1, i
E2: foo


Is there a reason the exception type is not the same?
Is this behavior something that should be expected?
--
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 18 '05 #1
6 1457
RT Lange wrote:
class E1(Exception): pass class E2(E1): pass i = E2('foo')
raise E1(i) Traceback (most recent call last):
File "<pyshell#5>", line 1, in ?
raise E1(i)
E1: foo raise E1, i Traceback (most recent call last):
File "<pyshell#6>", line 1, in ?
raise E1, i
E2: foo


Is there a reason the exception type is not the same?
Is this behavior something that should be expected?


This is interesting. I thought of

raise E, o # 1

and

raise E(o) # 2

as equivalent. Well, until today:

"If the first object is a class, it becomes the type of the exception. The
second object is used to determine the exception value: If it is an
instance of the class, the instance becomes the exception value. If the
second object is a tuple, it is used as the argument list for the class
constructor; if it is None, an empty argument list is used, and any other
object is treated as a single argument to the constructor. The instance so
created by calling the constructor is used as the exception value."

(quoted from http://www.python.org/doc/current/ref/raise.html)

So, if isinstance(o, E), the first form is indeed equivalent to

raise o

and your code works as advertised.
Peter

Jul 18 '05 #2
In article <op**************@newgroups.bellsouth.net>,
RT Lange <wh*********@yahoo.com> wrote:
class E1(Exception): pass class E2(E1): pass i = E2('foo')
raise E1(i)

Traceback (most recent call last):
File "<pyshell#5>", line 1, in ?
raise E1(i)
E1: foo


<scratch head> Why are you passing an exception instance to the
constructor for a different exception?
--
Aahz (aa**@pythoncraft.com) <*> http://www.pythoncraft.com/

Weinberg's Second Law: If builders built buildings the way programmers wrote
programs, then the first woodpecker that came along would destroy civilization.
Jul 18 '05 #3
On Sun, 07 Dec 2003 18:39:54 +0100, Peter Otten <__*******@web.de> wrote:
RT Lange wrote:
> class E1(Exception): pass

> class E2(E1): pass

> i = E2('foo')
> raise E1(i)

Traceback (most recent call last):
File "<pyshell#5>", line 1, in ?
raise E1(i)
E1: foo
> raise E1, i

Traceback (most recent call last):
File "<pyshell#6>", line 1, in ?
raise E1, i
E2: foo
>


Is there a reason the exception type is not the same?
Is this behavior something that should be expected?


This is interesting. I thought of

raise E, o # 1

and

raise E(o) # 2

as equivalent. Well, until today:

"If the first object is a class, it becomes the type of the exception.
The
second object is used to determine the exception value: If it is an
instance of the class, the instance becomes the exception value. If the
second object is a tuple, it is used as the argument list for the class
constructor; if it is None, an empty argument list is used, and any other
object is treated as a single argument to the constructor. The instance
so
created by calling the constructor is used as the exception value."

(quoted from http://www.python.org/doc/current/ref/raise.html)

So, if isinstance(o, E), the first form is indeed equivalent to

raise o

but if o is an instance of an E subclass (hence isinstance(o, E) is still
true),
shouldn't the first form raise an exception with type E (not E's subclass)
and value o?

--
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 18 '05 #4
RT Lange wrote:
but if o is an instance of an E subclass (hence isinstance(o, E) is still
true),
shouldn't the first form raise an exception with type E (not E's subclass)
and value o?


Again:

"If it is an instance of the class, the *instance* *becomes* the *exception*
*value*"

Or, directly from the source:

/* if the value was not an instance, or is not an instance
whose class is (or is derived from) type, then use the
value as an argument to instantiation of the type
class.
*/

(comment in function PyErr_NormalizeException() in error.c)

As clear as you can get. I cannot comment on the rationale of that design
decision, though. I would replace the

raise E, args # disallow in 3.0?

form completely with

raise E(args)

which would avoid the ambiguity altogether.
Peter

PS: I think you owe me an answer to Aahz' pending question now :-)


Jul 18 '05 #5
Peter Otten <__*******@web.de> wrote in message news:<br************@news.t-online.com>...
"If it is an instance of the class, the *instance* *becomes* the *exception*
*value*"

this says nothing about the *type* of exception, just the *value*.
"6.9 The raise statement
....The first two objects are used to determine the type and value of
the exception.
If the first object is an instance, the TYPE of the exception is the
class of the instance, the instance itself is the VALUE, and the
second object must be None."
class E(Exception): pass i = E('foo')
try: raise i
except:
print sys.exc_info()[:2]
(<class __main__.E at 0x00A88090>, <__main__.E instance at
0x00A5A850>)

*makes perfect sense*

"If the first object is a class, it becomes the TYPE of the exception.
The second object is used to determine the exception value: If it is
an instance of the class, the instance becomes the exception VALUE."
try: raise Exception, i #first object is a class: becomes the type
#second object instance of (sub)class: becomes the valu
except:
print sys.exc_info()[:2]
(<class __main__.E at 0x00A88090>, <__main__.E instance at
0x00A5A850>)

*hmmm "Exception" did NOT become the TYPE of the exception*

As for why I was passing an exception instance to the
constructor for a different exception...just pointing out the
nonequivalence of the two forms.
Why would someone want to do this? Don't ask me.
I only use string exceptions. :)

RT
Jul 18 '05 #6
wh*********@yahoo.com (rt lange) wrote in message news:<b7*************************@posting.google.c om>...
*hmmm "Exception" did NOT become the TYPE of the exception*


One could argue that Exception is in fact the type of the exception.
import sys
class E(Exception): .... pass
.... try:

.... raise Exception, i
.... except:
.... print isinstance(sys.exc_info()[1], Exception)
....
True

It just so happens that the exception is also of type E. In fact
'except Exception:' will also catch the exception.

--
Shalabh
Jul 18 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

11 posts views Thread by Johan | last post: by
23 posts views Thread by Allin Cottrell | last post: by
9 posts views Thread by Girish | last post: by
2 posts views Thread by kpax | last post: by
36 posts views Thread by Chad Z. Hower aka Kudzu | last post: by
3 posts views Thread by Jess | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.