is parameter an iterable?

Bengt Richter bokr at oz.net
Wed Nov 16 17:39:19 EST 2005


On Wed, 16 Nov 2005 17:39:57 +0100, "Fredrik Lundh" <fredrik at pythonware.com> wrote:

>Rick Wotnaz wrote.
>
>> ... which leads me to belive that 'msg' is not type(str). It can be
>> coerced (str(msg).find works as expected). But what exactly is msg?
>> It appears to be of <type 'instance'>, and does not test equal to a
>> string.
>
>it's an instance of the exception type, of course.
>
>:::
>
>if you do
>
>    raise SomeError, value
>
>Python will actually do
>
>    raise SomeError(value)

Depending on what you mean by "actually" I guess ...
(I'm sure you know this and more ;-)

 >>> dis.dis(compile('raise SomeError, value','','exec'))
   1           0 LOAD_NAME                0 (SomeError)
               3 LOAD_NAME                1 (value)
               6 RAISE_VARARGS            2
               9 LOAD_CONST               0 (None)
              12 RETURN_VALUE
 >>> dis.dis(compile('raise SomeError(value)','','exec'))
   1           0 LOAD_NAME                0 (SomeError)
               3 LOAD_NAME                1 (value)
               6 CALL_FUNCTION            1
               9 RAISE_VARARGS            1
              12 LOAD_CONST               0 (None)
              15 RETURN_VALUE

I guess that comes from the grammar of the raise statement, i.e.,

    raise_stmt: 'raise' [test [',' test [',' test]]]

which allows up to three arguments for raise, apparently all general
expressions, but  with some specific run-time requirements for what
combinations of argument expression values are allowable.

I.e., it seems (I haven't looked in ceval.c(?)) that RAISE_VARARGS must
look at the first item in its count of args on the stack, and in the
SomeError, value case find an exception class, and decide to instantiate it
and throw the instance, but if it finds the instance ready made, as in
SomeError(value), it must skip the instantiation (and disallow further args BTW).

 >>> raise Exception, 'arg'
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
 Exception: arg
 >>> raise Exception('arg')
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
 Exception: arg

Those looks the same, but sensitivity to the type of the first arg is revealed by

 >>> raise Exception('arg'), 'what now?'
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
 TypeError: instance exception may not have a separate value

 >>> raise Exception('arg', 'what now?')
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
 Exception: ('arg', 'what now?')


>
>(that is, create a SomeError exception and pass the value as its
>first argument).
>
>you can use either form in your code (I prefer the latter myself).
>
Just to drive home the general expression allowability in raise,
and instance vs class as the first arg:

 >>> extab = [StopIteration('stop stop ;-)'), ValueError('wrong value')]

 >>> raise extab[1]
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
 ValueError: wrong value

 >>> raise extab[0]
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
 StopIteration: stop stop ;-)

 >>> extab = [StopIteration, 'stop stop ;-)', ValueError, 'wrong value']

 >>> raise extab[2], extab[3]
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
 ValueError: wrong value

 >>> raise extab[0], extab[1]
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
 StopIteration: stop stop ;-)

Ok, I'll stop ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list