Instance Exception Oddity: Implicit and Explicit not the same?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • RT Lange

    Instance Exception Oddity: Implicit and Explicit not the same?

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

    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/
  • Peter Otten

    #2
    Re: Instance Exception Oddity: Implicit and Explicit not the same?

    RT Lange wrote:
    [color=blue][color=green][color=darkred]
    >>>> class E1(Exception): pass[/color][/color]
    >[color=green][color=darkred]
    >>>> class E2(E1): pass[/color][/color]
    >[color=green][color=darkred]
    >>>> i = E2('foo')
    >>>> raise E1(i)[/color][/color]
    > Traceback (most recent call last):
    > File "<pyshell#5 >", line 1, in ?
    > raise E1(i)
    > E1: foo[color=green][color=darkred]
    >>>> raise E1, i[/color][/color]
    > Traceback (most recent call last):
    > File "<pyshell#6 >", line 1, in ?
    > raise E1, i
    > E2: foo[color=green][color=darkred]
    >>>>[/color][/color]
    >
    > Is there a reason the exception type is not the same?
    > Is this behavior something that should be expected?[/color]

    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



    Comment

    • Aahz

      #3
      Re: Instance Exception Oddity: Implicit and Explicit not the same?

      In article <oprztjkwvjuwzg lb@newgroups.be llsouth.net>,
      RT Lange <whiteywidow@ya hoo.com> wrote:[color=blue][color=green][color=darkred]
      >>>> class E1(Exception): pass[/color][/color]
      >[color=green][color=darkred]
      >>>> class E2(E1): pass[/color][/color]
      >[color=green][color=darkred]
      >>>> i = E2('foo')
      >>>> raise E1(i)[/color][/color]
      >Traceback (most recent call last):
      > File "<pyshell#5 >", line 1, in ?
      > raise E1(i)
      >E1: foo[/color]

      <scratch head> Why are you passing an exception instance to the
      constructor for a different exception?
      --
      Aahz (aahz@pythoncra ft.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.

      Comment

      • RT Lange

        #4
        Re: Instance Exception Oddity: Implicit and Explicit not the same?

        On Sun, 07 Dec 2003 18:39:54 +0100, Peter Otten <__peter__@web. de> wrote:
        [color=blue]
        > RT Lange wrote:
        >[color=green][color=darkred]
        >>>>> class E1(Exception): pass[/color]
        >>[color=darkred]
        >>>>> class E2(E1): pass[/color]
        >>[color=darkred]
        >>>>> i = E2('foo')
        >>>>> raise E1(i)[/color]
        >> Traceback (most recent call last):
        >> File "<pyshell#5 >", line 1, in ?
        >> raise E1(i)
        >> E1: foo[color=darkred]
        >>>>> raise E1, i[/color]
        >> Traceback (most recent call last):
        >> File "<pyshell#6 >", line 1, in ?
        >> raise E1, i
        >> E2: foo[color=darkred]
        >>>>>[/color]
        >>
        >> Is there a reason the exception type is not the same?
        >> Is this behavior something that should be expected?[/color]
        >
        > 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
        >[/color]
        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/

        Comment

        • Peter Otten

          #5
          Re: Instance Exception Oddity: Implicit and Explicit not the same?

          RT Lange wrote:
          [color=blue]
          > 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?[/color]

          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_Normalize Exception() 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 :-)




          Comment

          • rt lange

            #6
            Re: Instance Exception Oddity: Implicit and Explicit not the same?

            Peter Otten <__peter__@web. de> wrote in message news:<br4cov$h7 $01$1@news.t-online.com>...
            [color=blue]
            > "If it is an instance of the class, the *instance* *becomes* the *exception*
            > *value*"[/color]
            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."
            [color=blue][color=green][color=darkred]
            >>> class E(Exception): pass[/color][/color][/color]
            [color=blue][color=green][color=darkred]
            >>> i = E('foo')
            >>> try:[/color][/color][/color]
            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."
            [color=blue][color=green][color=darkred]
            >>> try:[/color][/color][/color]
            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>)[color=blue][color=green][color=darkred]
            >>>[/color][/color][/color]
            *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...jus t 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

            Comment

            • Shalabh Chaturvedi

              #7
              Re: Instance Exception Oddity: Implicit and Explicit not the same?

              whiteywidow@yah oo.com (rt lange) wrote in message news:<b771ffdd. 0312091423.d1ac c66@posting.goo gle.com>...
              [color=blue]
              > *hmmm "Exception" did NOT become the TYPE of the exception*[/color]

              One could argue that Exception is in fact the type of the exception.
              [color=blue][color=green][color=darkred]
              >>> import sys
              >>> class E(Exception):[/color][/color][/color]
              .... pass
              ....[color=blue][color=green][color=darkred]
              >>> try:[/color][/color][/color]
              .... 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

              Comment

              Working...