[Python-Dev] Style for raising exceptions (python-dev Summary for 2005-08-01 through 2005-08-15 [draft])

M.-A. Lemburg mal at egenix.com
Fri Aug 26 10:12:12 CEST 2005

Guido van Rossum wrote:
> On 8/25/05, M.-A. Lemburg <mal at egenix.com> wrote:
>>I must have missed this one:
>>>Style for raising exceptions
>>>Guido explained that these days exceptions should always be raised as::
>>>    raise SomeException("some argument")
>>>instead of::
>>>    raise SomeException, "some argument"
>>>The second will go away in Python 3.0, and is only present now for backwards
>>>compatibility.  (It was  necessary when strings could be exceptions, in
>>>order to pass both the exception "type" and message.)   PEPs 8_ and 3000_
>>>were accordingly updated.
>>AFAIR, the second form was also meant to be able to defer
>>the instantiation of the exception class until really
>>needed in order to reduce the overhead related to raising
>>exceptions in Python.
>>However, that optimization never made it into the implementation,
>>I guess.
> Something equivalent is used internally in the C code, but that
> doesn't mean we'll need it in Python code. The optimization only works
> if the exception is also *caught* in C code, BTW (it is instantiated
> as soon as it is handled by a Python except clause).

Ah, I knew it was in there somewhere (just couldn't find yesterday
when I was looking for the optimization :-).

> Originally, the second syntax was the only available syntax, because
> all we had were string exceptions. Now that string exceptions are dead
> (although not yet buried :) I really don't see why we need to keep
> both versions of the syntax; Python 3.0 will only have one version.

Actually, we do only have one version: the first syntax is just
a special case of the second (with the value argument set
to None).

I don't see a need for two or more syntaxes either, but most code
nowadays uses the second variant (I don't know of any code that
uses the traceback argument), which puts up a high barrier
for changes.

This is from a comment in ceval.c:

	/* We support the following forms of raise:
	   raise <class>, <classinstance>
	   raise <class>, <argument tuple>
	   raise <class>, None
	   raise <class>, <argument>
	   raise <classinstance>, None
	   raise <string>, <object>
	   raise <string>, None

	   An omitted second argument is the same as None.

	   In addition, raise <tuple>, <anything> is the same as
	   raising the tuple's first item (and it better have one!);
	   this rule is applied recursively.

	   Finally, an optional third argument can be supplied, which
	   gives the traceback to be substituted (useful when
	   re-raising an exception after examining it).  */

That's quite a list of combinations that will all break
in Python 3.0 if we only allow "raise <classinstance>".

I guess the reason for most code using the variante "raise
<class>, <argument tuple>" is that it simply looks a lot
like the corresponding "except <class>, errorobj" clause.

> (We're still debating what to do with the traceback argument; wanna
> revive PEP 344?)
> If you need to raise exceptions fast, pre-instantiate an instance.

Ideally, I'd like Python to take care of such optimizations
rather than having to explicitly code for them:

If I write "raise ValueError, 'bad format'" and then
catch the error with just "except ValueError", there would
be no need for Python to actually instantiate the
exception object.

OTOH, lazy instantiation may have unwanted side-effects
(just like any lazy evaluation), e.g. the instantiation
could result in another exception to get raised.

Can't have 'em all, I guess.

Marc-Andre Lemburg

Professional Python Services directly from the Source  (#1, Aug 26 2005)
>>> Python/Zope Consulting and Support ...        http://www.egenix.com/
>>> mxODBC.Zope.Database.Adapter ...             http://zope.egenix.com/
>>> mxODBC, mxDateTime, mxTextTools ...        http://python.egenix.com/

::: Try mxODBC.Zope.DA for Windows,Linux,Solaris,FreeBSD for free ! ::::

More information about the Python-Dev mailing list