PEP 317: Eliminate Implicit Exception Instantiation

0 views
Skip to first unread message

Steven Taschuk

unread,
Jun 9, 2003, 2:18:30 AM6/9/03
to
PEP: 317
Title: Eliminate Implicit Exception Instantiation
Version: $Revision: 1.2 $
Last-Modified: $Date: 2003/06/09 04:43:39 $
Author: Steven Taschuk <stas...@telusplanet.net>
Status: Draft
Type: Standards Track
Content-Type: text/x-rst
Created: 06-May-2003
Python-Version: 2.4
Post-History: 09-Jun-2003


Abstract
========

"For clarity in new code, the form ``raise class(argument, ...)``
is recommended (i.e. make an explicit call to the constructor)."

-- Guido van Rossum, in 1997 [1]_

This PEP proposes the formal deprecation and eventual elimination of
forms of the ``raise`` statement which implicitly instantiate an
exception. For example, statements such as ::

raise HullBreachError
raise KitchenError, 'all out of baked beans'

must under this proposal be replaced with their synonyms ::

raise HullBreachError()
raise KitchenError('all out of baked beans')

Note that these latter statements are already legal, and that this PEP
does not change their meaning.

Eliminating these forms of ``raise`` makes it impossible to use string
exceptions; accordingly, this PEP also proposes the formal deprecation
and eventual elimination of string exceptions.

Adoption of this proposal breaks backwards compatibility. Under the
proposed implementation schedule, Python 2.4 will introduce warnings
about uses of ``raise`` which will eventually become incorrect, and
Python 3.0 will eliminate them entirely. (It is assumed that this
transition period -- 2.4 to 3.0 -- will be at least one year long, to
comply with the guidelines of PEP 5 [2]_.)


Motivation
==========

String Exceptions
-----------------

It is assumed that removing string exceptions will be uncontroversial,
since it has been intended since at least Python 1.5, when the
standard exception types were changed to classes [1]_.

For the record: string exceptions should be removed because the
presence of two kinds of exception complicates the language without
any compensation. Instance exceptions are superior because, for
example,

* the class-instance relationship more naturally expresses the
relationship between the exception type and value,

* they can be organized naturally using superclass-subclass
relationships, and

* they can encapsulate error-reporting behaviour (for example).


Implicit Instantiation
----------------------

Guido's 1997 essay [1]_ on changing the standard exceptions into
classes makes clear why ``raise`` can instantiate implicitly:

"The raise statement has been extended to allow raising a class
exception without explicit instantiation. The following forms,
called the "compatibility forms" of the raise statement [...] The
motivation for introducing the compatibility forms was to allow
backward compatibility with old code that raised a standard
exception."

For example, it was desired that pre-1.5 code which used string
exception syntax such as ::

raise TypeError, 'not an int'

would work both on versions of Python in which ``TypeError`` was a
string, and on versions in which it was a class.

When no such consideration obtains -- that is, when the desired
exception type is not a string in any version of the software which
the code must support -- there is no good reason to instantiate
implicitly, and it is clearer not to. For example:

1. In the code ::

try:
raise MyError, raised
except MyError, caught:
pass

the syntactic parallel between the ``raise`` and ``except``
statements strongly suggests that ``raised`` and ``caught`` refer
to the same object. For string exceptions this actually is the
case, but for instance exceptions it is not.

2. When instantiation is implicit, it is not obvious when it occurs,
for example, whether it occurs when the exception is raised or when
it is caught. Since it actually happens at the ``raise``, the code
should say so.

(Note that at the level of the C API, an exception can be "raised"
and "caught" without being instantiated; this is used as an
optimization by, for example, ``PyIter_Next``. But in Python, no
such optimization is or should be available.)

3. An implicitly instantiating ``raise`` statement with no arguments,
such as ::

raise MyError

simply does not do what it says: it does not raise the named
object.

4. The equivalence of ::

raise MyError
raise MyError()

conflates classes and instances, creating a possible source of
confusion for beginners. (Moreover, it is not clear that the
interpreter could distinguish between a new-style class and an
instance of such a class, so implicit instantiation may be an
obstacle to any future plan to let exceptions be new-style
objects.)

In short, implicit instantiation has no advantages other than
backwards compatibility, and so should be phased out along with what
it exists to ensure compatibility with, namely, string exceptions.


Specification
=============

The syntax of ``raise_stmt`` [3]_ is to be changed from ::

raise_stmt ::= "raise" [expression ["," expression ["," expression]]]

to ::

raise_stmt ::= "raise" [expression ["," expression]]

If no expressions are present, the ``raise`` statement behaves as it
does presently: it re-raises the last exception that was active in the
current scope, and if no exception has been active in the current
scope, a ``TypeError`` is raised indicating that this is the problem.

Otherwise, the first expression is evaluated, producing the *raised
object*. Then the second expression is evaluated, if present,
producing the *substituted traceback*. If no second expression is
present, the substituted traceback is ``None``.

The raised object must be an instance. The class of the instance is
the exception type, and the instance itself is the exception value.
If the raised object is not an instance -- for example, if it is a
class or string -- a ``TypeError`` is raised.

If the substituted traceback is not ``None``, it must be a traceback
object, and it is substituted instead of the current location as the
place where the exception occurred. If it is neither a traceback
object nor ``None``, a ``TypeError`` is raised.


Backwards Compatibility
=======================

Migration Plan
--------------

Future Statement
''''''''''''''''

Under the future statement [4]_ ::

from __future__ import raise_with_two_args

the syntax and semantics of the ``raise`` statement will be as
described above. This future feature is to appear in Python 2.4; its
effect is to become standard in Python 3.0.

As the examples below illustrate, this future statement is only needed
for code which uses the substituted traceback argument to ``raise``;
simple exception raising does not require it.


Warnings
''''''''

Three new warnings [5]_, all of category ``DeprecationWarning``, are
to be issued to point out uses of ``raise`` which will become
incorrect under the proposed changes.

The first warning is issued when a ``raise`` statement is executed in
which the first expression evaluates to a string. The message for
this warning is::

raising strings will be impossible in the future

The second warning is issued when a ``raise`` statement is executed in
which the first expression evaluates to a class. The message for this
warning is::

raising classes will be impossible in the future

The third warning is issued when a ``raise`` statement with three
expressions is compiled. (Not, note, when it is executed; this is
important because the ``SyntaxError`` which this warning presages will
occur at compile-time.) The message for this warning is::

raising with three arguments will be impossible in the future

These warnings are to appear in Python 2.4, and disappear in Python
3.0, when the conditions which cause them are simply errors.


Examples
--------

Code Using Implicit Instantiation
'''''''''''''''''''''''''''''''''

Code such as ::

class MyError(Exception):
pass

raise MyError, 'spam'

will issue a warning when the ``raise`` statement is executed. The
``raise`` statement should be changed to instantiate explicitly::

raise MyError('spam')


Code Using String Exceptions
''''''''''''''''''''''''''''

Code such as ::

MyError = 'spam'
raise MyError, 'eggs'

will issue a warning when the ``raise`` statement is executed. The
exception type should be changed to a class::

class MyError(Exception):
pass

and, as in the previous example, the ``raise`` statement should be
changed to instantiate explicitly ::

raise MyError('eggs')


Code Supplying a Traceback Object
'''''''''''''''''''''''''''''''''

Code such as ::

raise MyError, 'spam', mytraceback

will issue a warning when compiled. The statement should be changed
to ::

raise MyError('spam'), mytraceback

and the future statement ::

from __future__ import raise_with_two_args

should be added at the top of the module. Note that adding this
future statement also turns the other two warnings into errors, so the
changes described in the previous examples must also be applied.

The special case ::

raise sys.exc_type, sys.exc_info, sys.exc_traceback

(which is intended to re-raise a previous exception) should be changed
simply to ::

raise


A Failure of the Plan
'''''''''''''''''''''

It may occur that a ``raise`` statement which raises a string or
implicitly instantiates is not executed in production or testing
during the phase-in period for this PEP. In that case, it will not
issue any warnings, but will instead suddenly fail one day in Python
3.0 or a subsequent version. (The failure is that the wrong exception
gets raised, namely a ``TypeError`` complaining about the arguments to
``raise``, instead of the exception intended.)

Such cases can be made rarer by prolonging the phase-in period; they
cannot be made impossible short of issuing at compile-time a warning
for every ``raise`` statement.


References
==========

.. [1] "Standard Exception Classes in Python 1.5", Guido van Rossum.
http://www.python.org/doc/essays/stdexceptions.html

.. [2] "Guidelines for Language Evolution", Paul Prescod.
http://www.python.org/peps/pep-0005.html

.. [3] "Python Language Reference", Guido van Rossum.
http://www.python.org/doc/current/ref/raise.html

.. [4] PEP 236 "Back to the __future__", Tim Peters.
http://www.python.org/peps/pep-0236.html

.. [5] PEP 230 "Warning Framework", Guido van Rossum.
http://www.python.org/peps/pep-0230.html


Copyright
=========

This document has been placed in the public domain.



..
Local Variables:
mode: indented-text
indent-tabs-mode: nil
sentence-end-double-space: t
fill-column: 70
End:

Erik Max Francis

unread,
Jun 9, 2003, 5:54:03 AM6/9/03
to
Steven Taschuk wrote:

> This PEP proposes the formal deprecation and eventual elimination of
> forms of the ``raise`` statement which implicitly instantiate an
> exception.

I agree with all this, and support the PEP, but must admit it's going to
involve some effort changing. I've gotten way too used to the old way
of raising exceptions.

--
Erik Max Francis && m...@alcyone.com && http://www.alcyone.com/max/
__ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
/ \ Together we can take this one day at a time
\__/ Sweetbox

Terry Reedy

unread,
Jun 9, 2003, 9:43:39 AM6/9/03
to
I would change 'raise_with_two_args' to something shorter, like
'raise_instance' or even 'new_raise'.

TJR


Bernhard Herzog

unread,
Jun 9, 2003, 10:46:59 AM6/9/03
to
Steven Taschuk <stas...@telusplanet.net> writes:

[...]


> Specification
> =============
>
> The syntax of ``raise_stmt`` [3]_ is to be changed from ::
>
> raise_stmt ::= "raise" [expression ["," expression ["," expression]]]
>
> to ::
>
> raise_stmt ::= "raise" [expression ["," expression]]
>

[...]
> Warnings
> ''''''''
[...]


> The third warning is issued when a ``raise`` statement with three
> expressions is compiled. (Not, note, when it is executed; this is
> important because the ``SyntaxError`` which this warning presages will
> occur at compile-time.) The message for this warning is::
>
> raising with three arguments will be impossible in the future
>
> These warnings are to appear in Python 2.4, and disappear in Python
> 3.0, when the conditions which cause them are simply errors.

How do I write code that raises and exception with an explicit traceback
object that works both with Python 2.4 and at least 2.3 (preferably 2.2
and 2.1 as well) and that does not issue warnings?

Bernhard

--
Intevation GmbH http://intevation.de/
Sketch http://sketch.sourceforge.net/
MapIt! http://www.mapit.de/

Steven Taschuk

unread,
Jun 9, 2003, 12:50:37 PM6/9/03
to
Quoth Bernhard Herzog:
[...]

> How do I write code that raises and exception with an explicit traceback
> object that works both with Python 2.4 and at least 2.3 (preferably 2.2
> and 2.1 as well) and that does not issue warnings?

Not possible as the proposal stands (except, of course, by simply
suppressing the warnings).

This is a defect, but I couldn't come up with anything better when
I was writing the PEP. Part of my problem here is that I'm not
familiar enough with real-life uses of the traceback argument. Do
you use it?

--
Steven Taschuk stas...@telusplanet.net
"I may be wrong but I'm positive." -- _Friday_, Robert A. Heinlein

Evan Simpson

unread,
Jun 9, 2003, 1:13:04 PM6/9/03
to
Steven Taschuk wrote:
> Eliminating these forms of ``raise`` makes it impossible to use string
> exceptions; accordingly, this PEP also proposes the formal deprecation
> and eventual elimination of string exceptions.

Rather than eliminating string exceptions, I suggest a new (ab)use and
semantics for them, based on my old "break '<string>', continue
'<string>'" proposal:

1. At compile time, require "raise '<string>'" to be lexically enclosed
by a matching "try: ... except '<string>':".

2. Treat such combinations as though they were a goto/label pair. In
other words, rather than invoking the exception machinery, compile the
"raise" into a jump bytecode.

This would allow for labelled exits from a block of code. Note that
"raise 'foo'" without a matching "except 'foo':' is a SyntaxError, so
this is a very localized, tame goto, and typos in the strings are highly
likely to be caught at compile-time.

Abstracted Example:

try:
m = re.search(<first pattern>)
if m:
if <expression involving m>:
raise 'First case'
if <expression involving m>:
raise 'Second case'
m = re.search(<second pattern>)
if m:
if <expression involving m>:
raise 'First case'
if <expression involving m>:
raise 'Second case'
if <some other test>:
raise 'Second case'
return
except 'First case':
<handle the first case>
except 'Second case':
<handle the second case>
<code common to both cases>

I've both written and encountered code that has this sort of logical
structure, but which had to be written as some variation on:

case = None
m = re.search(<first pattern>)
if m:
if <expression involving m>:
case = 1
elif <expression involving m>:
case = 2
if case is None:
m = re.search(<second pattern>)
if m:
if <expression involving m>:
case = 1
elif <expression involving m>:
case = 2
if case is None and <some other test>:
case = 2
if case is None:
return
if case == 1:
<handle the first case>
else:
<handle the second case>
<code common to both cases>

Cheers,

Evan @ 4-am

Beni Cherniavsky

unread,
Jun 9, 2003, 1:47:45 PM6/9/03
to
Bernhard Herzog wrote on 2003-06-09:

> Steven Taschuk <stas...@telusplanet.net> writes:
>
> [...]
> > Specification
> > =============
> >
> > The syntax of ``raise_stmt`` [3]_ is to be changed from ::
> >
> > raise_stmt ::= "raise" [expression ["," expression ["," expression]]]
> >
> > to ::
> >
> > raise_stmt ::= "raise" [expression ["," expression]]
> >
> [...]
> > Warnings
> > ''''''''
> [...]
> > The third warning is issued when a ``raise`` statement with three
> > expressions is compiled. (Not, note, when it is executed; this is
> > important because the ``SyntaxError`` which this warning presages will
> > occur at compile-time.) The message for this warning is::
> >
> > raising with three arguments will be impossible in the future
> >
> > These warnings are to appear in Python 2.4, and disappear in Python
> > 3.0, when the conditions which cause them are simply errors.
>
> How do I write code that raises and exception with an explicit traceback
> object that works both with Python 2.4 and at least 2.3 (preferably 2.2
> and 2.1 as well) and that does not issue warnings?
>

Good question. Why not autodetect this? Currently__:

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.

__ http://www.python.org/dev/doc/devel/ref/raise.html

So if it's already an instance and there are two objects and the
second object is not None, let's treat it as a traceback. More magic,
less hassle. Wait, we wanted less magic - but this is OK <wink>. I
even propose this part to be put into 2.3.

This reminds us of the question what is an instance. This is hard to
define with new-style classes but "anything that is not callable" is a
good definition (because if it's a class we want to call it anyway).
When this PEP will be executed completely, this question can be
dropped because the first object will be assumed to always be an
instance.

--
Beni Cherniavsky <cb...@users.sf.net>

Steven Taschuk

unread,
Jun 9, 2003, 1:29:07 PM6/9/03
to
Quoth Terry Reedy:

> I would change 'raise_with_two_args' to something shorter, like
> 'raise_instance' or even 'new_raise'.

I'm open to such suggestions, but do note that almost all users
will have no need for this future statement -- it's only useful to
users who need the traceback argument. The present name is
intended to suit such people, who will be adding it to deal with a
warning that says "raising with three arguments will be impossible
in the future".

--
Steven Taschuk "[W]e must be very careful when we give advice
stas...@telusplanet.net to younger people: sometimes they follow it!"
-- "The Humble Programmer", Edsger Dijkstra

Bernhard Herzog

unread,
Jun 9, 2003, 2:31:12 PM6/9/03
to
Steven Taschuk <stas...@telusplanet.net> writes:

> Quoth Bernhard Herzog:
> [...]
> > How do I write code that raises and exception with an explicit traceback
> > object that works both with Python 2.4 and at least 2.3 (preferably 2.2
> > and 2.1 as well) and that does not issue warnings?
>
> Not possible as the proposal stands (except, of course, by simply
> suppressing the warnings).

Suppressing it is pretty awkward because it happens at compile time so I
can't put the code to suppress it into the modules containing the
deprecated raise.

> This is a defect, but I couldn't come up with anything better when
> I was writing the PEP.

The easiest would be to introduce the new syntax with the future
statement in 2.4 and start issuing warnings several releases later.

I'd also recomment not issuing warnings about "raise SomeClass, val" in
2.4 either except perhaps when explicitly switched on.

Warnings for string exceptions are fine with me, though.

> Part of my problem here is that I'm not
> familiar enough with real-life uses of the traceback argument. Do
> you use it?

Yes, occasionally.

Steven Taschuk

unread,
Jun 9, 2003, 3:05:37 PM6/9/03
to
Quoth Bernhard Herzog:
> Steven Taschuk <stas...@telusplanet.net> writes:
[using raise w/ traceback, without warnings, in all 2.x]

> > This is a defect, but I couldn't come up with anything better when
> > I was writing the PEP.
>
> The easiest would be to introduce the new syntax with the future
> statement in 2.4 and start issuing warnings several releases later.
>
> I'd also recomment not issuing warnings about "raise SomeClass, val" in
> 2.4 either except perhaps when explicitly switched on.

Ah. Yes, a slower migration is certainly possible. One of my
reasons for submitting the PEP was to find out how quickly such a
change could occur -- you're not the only person to suggest it
would have to be slower than I propose.

[...]


> > Part of my problem here is that I'm not
> > familiar enough with real-life uses of the traceback argument. Do
> > you use it?
>
> Yes, occasionally.

I'd like to hear more about this -- in what circumstances, and to
what end?

--
Steven Taschuk stas...@telusplanet.net
"What I find most baffling about that song is that it was not a hit."
-- Tony Dylan Davis (CKUA)

Steven Taschuk

unread,
Jun 9, 2003, 2:21:17 PM6/9/03
to
Quoth Beni Cherniavsky:
[...]

> So if it's already an instance and there are two objects and the
> second object is not None, let's treat it as a traceback. More magic,
> less hassle. Wait, we wanted less magic - but this is OK <wink>. I
> even propose this part to be put into 2.3.

I don't think this meets Bernard's objective, which is to have
traceback-using raise statements which run on all 2.x without
warnings. Whatever is done with 2.3 (and I doubt at this point
any such change would be accepted), only the three-argument form
will work in <= 2.2, and it is exactly this form for which the PEP
proposes warnings in >= 2.4.

Your suggestion does, however, obviate the need for the future
statement, at the cost of, as you say, more magic during the
transition period.

> This reminds us of the question what is an instance. This is hard to
> define with new-style classes but "anything that is not callable" is a
> good definition (because if it's a class we want to call it anyway).
> When this PEP will be executed completely, this question can be
> dropped because the first object will be assumed to always be an
> instance.

One reason for the PEP, in fact. (Though only alluded to briefly
in the Motivation section.)

Another approach is to require that exceptions be instances of
Exception. Then we could do
if isinstance(first_obj, Exception):
# first_obj is exception object
elif issubclass(first_obj, Exception):
# instantiate implicitly
else:
# error
Then eventually Exception could be made new-style without an
instance/class detection problem, I think.

--
Steven Taschuk o- @
stas...@telusplanet.net 7O )
" (

Bernhard Herzog

unread,
Jun 9, 2003, 4:33:13 PM6/9/03
to
Steven Taschuk <stas...@telusplanet.net> writes:

> Quoth Bernhard Herzog:
> > Steven Taschuk <stas...@telusplanet.net> writes:
[...]
> > > Part of my problem here is that I'm not
> > > familiar enough with real-life uses of the traceback argument. Do
> > > you use it?
> >
> > Yes, occasionally.
>
> I'd like to hear more about this -- in what circumstances, and to
> what end?

One is in the XFig import filter in Sketch (paraphrasing a bit):


try:
# ...
while line:
tokens = tokenize(line, 1)
# dispatch on tokens[0]
# ...
line = self.readline()
except SketchLoadError, value:
raise SketchLoadError('%d:%s' % (self.lineno, str(value))), None,\
sys.exc_traceback

So, basically it's there to put some more information into the error
message. Not all places where SketchLoadError is raised have access to
the line number so it can't easily be done in other ways.

I'm not sure why it uses exc_traceback instead of sys.exc_info()[2] but
the xfig filter is quite old and the code in question might predate
Python 1.5 where exc_info() was introduced. Anyway, Sketch doesn't use
threads so it shouldn't be a problem unless somebody now goes and starts
deprecating sys.exc_traceback ;-)

Ed Avis

unread,
Jun 9, 2003, 5:16:26 PM6/9/03
to
Steven Taschuk <stas...@telusplanet.net> writes:

> raise_stmt ::= "raise" [expression ["," expression]]

Why not go further and make it look like a normal function call, that
can take zero one or two arguments?

raise_stmt ::= "raise" "(" [expression ["," expression]] ")"

No arguments - raise() - would re-raise the currently active
exception, and so on.

--
Ed Avis <e...@membled.com>

Gerrit Holl

unread,
Jun 9, 2003, 5:32:01 PM6/9/03
to

Maybe raise could even be made a builtin-function instead of a statement?
I think there should be as few statements as possible.
Or would it be impossible because of Python's internals? I know
nothing about them...

yours,
Gerrit.

--
250. If while an ox is passing on the street (market) some one push it,
and kill it, the owner can set up no claim in the suit (against the
hirer).
-- 1780 BC, Hammurabi, Code of Law
--
Asperger Syndroom - een persoonlijke benadering:
http://people.nl.linux.org/~gerrit/
Het zijn tijden om je zelf met politiek te bemoeien:
http://www.sp.nl/

Steven Taschuk

unread,
Jun 9, 2003, 6:02:55 PM6/9/03
to
Quoth Bernhard Herzog:
[solicited example of use of traceback argument to raise]

> except SketchLoadError, value:
> raise SketchLoadError('%d:%s' % (self.lineno, str(value))), None,\
> sys.exc_traceback
>
> So, basically it's there to put some more information into the error
> message. Not all places where SketchLoadError is raised have access to
> the line number so it can't easily be done in other ways.

Yes, this makes sense. It seems to me a bit odd to create a new
exception object, though; would it work to mutate the existing
SketchLoadError and re-raise it?

class SketchLoadError(Exception):
def __init__(self, msg, lineno=None):
Exception.__init__(self, msg, lineno)
self.msg = msg
self.lineno = lineno
def __str__(self):
if self.lineno is None:
return str(self.msg)
else:
return '%s:%s' % (self.lineno, self.msg)

try:
# ...
except SketchLoadError, e:
e.lineno = lineno
raise

(I admit, of course, that this is a nontrivial change. I'm just
trying to get a handle on the use case.)

[...]


> threads so it shouldn't be a problem unless somebody now goes and starts
> deprecating sys.exc_traceback ;-)

It's been deprecated since 1.5 according to the Library Reference.
<wink>

--
Steven Taschuk stas...@telusplanet.net
"Telekinesis would be worth patenting." -- James Gleick

Steven Taschuk

unread,
Jun 9, 2003, 7:11:39 PM6/9/03
to
Quoth Ed Avis:

> Steven Taschuk <stas...@telusplanet.net> writes:
>
> > raise_stmt ::= "raise" [expression ["," expression]]
>
> Why not go further and make it look like a normal function call, that
> can take zero one or two arguments?
>
> raise_stmt ::= "raise" "(" [expression ["," expression]] ")"

Two reasons:

First, it would increase the backwards incompatibility, which is
already quite large. Under such a change, *all* raise statements
would need to be revised; under the change proposed, those who
have been using the One True Syntax for raising exceptions (i.e.,
instantiating explicitly) are exempt.

Second, I don't object to raise being a statement; in particular,
I don't think its being a statement makes any code less clear.
Implicit exception instantiation, however, I do believe to be
significantly less clear than explicit instantiation.

(I also don't have any particular wish to use raise in lambdas. I
have followed the timbot's alleged injunction to learn to love the
return key.)

--
Steven Taschuk Aral: "Confusion to the enemy, boy."
stas...@telusplanet.net Mark: "Turn-about is fair play, sir."
-- _Mirror Dance_, Lois McMaster Bujold

Greg Ewing (using news.cis.dfn.de)

unread,
Jun 9, 2003, 10:42:21 PM6/9/03
to
Evan Simpson wrote:
> 2. Treat such combinations as though they were a goto/label pair. In
> other words, rather than invoking the exception machinery, compile the
> "raise" into a jump bytecode.

Ironically, break and continue do actually invoke something
not altogether completely unlike the exception machinery!

They're not just jumps - they have to unwind the exception
handler stack so that finallies get executed (and I think
they unwind for-loop contexts, too). So this mightn't buy
you all that much.

--
Greg Ewing, Computer Science Dept,
University of Canterbury,
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg

Terry Reedy

unread,
Jun 9, 2003, 11:00:03 PM6/9/03
to

"Evan Simpson" <ev...@4-am.com> wrote in message
news:mailman.1055178857...@python.org...

> Rather than eliminating string exceptions,

On PyDev, Guido stated clearly that Python 3 will not have string
exceptions. So discussion is better aimed at other issues.

TJR


Aahz

unread,
Jun 10, 2003, 12:57:49 AM6/10/03
to
In article <l1brx7d...@budvar.future-i.net>,

Ed Avis <e...@membled.com> wrote:
>
>Why not go further and make it look like a normal function call, that
>can take zero one or two arguments?
>
> raise_stmt ::= "raise" "(" [expression ["," expression]] ")"
>
>No arguments - raise() - would re-raise the currently active
>exception, and so on.

Well, that would essentially make it no longer a statement. raise
pretty much needs to remain a statement to fit in with the try/except
control structure.
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/

"If you don't know what your program is supposed to do, you'd better not
start writing it." --Dijkstra

Bernhard Herzog

unread,
Jun 10, 2003, 4:45:49 AM6/10/03
to
Steven Taschuk <stas...@telusplanet.net> writes:

> Quoth Bernhard Herzog:
> [solicited example of use of traceback argument to raise]
> > except SketchLoadError, value:
> > raise SketchLoadError('%d:%s' % (self.lineno, str(value))), None,\
> > sys.exc_traceback
> >
> > So, basically it's there to put some more information into the error
> > message. Not all places where SketchLoadError is raised have access to
> > the line number so it can't easily be done in other ways.
>
> Yes, this makes sense. It seems to me a bit odd to create a new
> exception object, though; would it work to mutate the existing
> SketchLoadError and re-raise it?

In this particular case, yes. There are other cases where the exception
type is different too, but I'm not sure anymore whether that really is a
good idea.

> > threads so it shouldn't be a problem unless somebody now goes and starts
> > deprecating sys.exc_traceback ;-)
>
> It's been deprecated since 1.5 according to the Library Reference.
> <wink>

Yes, but Python doesn't issue warnings about it. Actually, issuing
deprecation warnings for exc_traceback and friends might be a good idea.
The alternative has been available since 1.5 and it is a potential
source of bugs. It would be far less controversial than the proposed
syntax change for the raise statement, I think.

Gerrit Holl

unread,
Jun 10, 2003, 5:32:05 AM6/10/03
to
Steven Taschuk wrote:
> raise MyError()

Just curious: am I the only one who always does this and is
accustomed to this style?

11:30:26:4:gerrit@stopcontact:~/cvs/brian$ grep "raise " *.py
basesprites.py: def next(self): raise StopIteration()
basesprites.py: raise errors.UndefinedAttributeError(self.__class__, *missing)
basesprites.py: raise errors.SingleCollision(self, sprite)
basesprites.py: raise errors.OutsideArea(w, self.rect)
basesprites.py: raise errors.DataError("image", self)
basesprites.py: raise errors.UndefinedMethodError(self.__class__, 'getbullet')
basesprites.py: raise errors.UnableShooting(self)
basesprites.py: raise errors.ShootingReload(self, cf=self.frame, \
basesprites.py: raise errors.UnexspectedCollision(self, item, "I'm in a wall")
basesprites.py: raise TypeError("Bullet constructor takes 2-3 args")
brian.py:## raise SystemExit()
brian.py: raise errors.EndGame()
brian.py: raise NotImplementedError("please wait ;)")
brian.py: raise errors.EndGame()
DataServer.py: raise AttributeError(msg)
errors.py: raise UsageError("at least one attribute must be given")
level.py: raise errors.GivenUpSpritePlacement(spr, counter)
level.py: raise errors.SpriteTooLarge(self.world.size, (w, h))
level.py: raise errors.GivenUpSpritePlacement(wall, counter)
screen.py: raise NotImplementedError("only tiled mode supported, mode is", self.bgmode)
screen.py: raise errors.UsageError("mode must be one of %s" % self.modes)
util.py: ordering, and if list(s).sort() doesn't raise TypeError it's
util.py: raise Exception()

yours,
Gerrit.

--
50. If he give a cultivated corn-field or a cultivated sesame-field,
the corn or sesame in the field shall belong to the owner of the field,
and he shall return the money to the merchant as rent.

Steven Taschuk

unread,
Jun 10, 2003, 11:25:57 AM6/10/03
to
Quoth Gerrit Holl:

> Steven Taschuk wrote:
> > raise MyError()
>
> Just curious: am I the only one who always does this and is
> accustomed to this style?

No; I too always instantiate explicitly. But you could probably
guess that.

Steven Taschuk

unread,
Jun 10, 2003, 11:25:44 AM6/10/03
to
Quoth Bernhard Herzog:
[...]

> Yes, but Python doesn't issue warnings about it. Actually, issuing
> deprecation warnings for exc_traceback and friends might be a good idea.
> The alternative has been available since 1.5 and it is a potential
> source of bugs. It would be far less controversial than the proposed
> syntax change for the raise statement, I think.

I agree entirely, but I don't see how such warnings could be
implemented. How can you hook into access of specific globals?

PyChecker could do it heuristically, I expect.

--
Steven Taschuk stas...@telusplanet.net
"[T]rue greatness is when your name is like ampere, watt, and fourier
-- when it's spelled with a lower case letter." -- R.W. Hamming

Bernhard Herzog

unread,
Jun 10, 2003, 2:24:36 PM6/10/03
to
Steven Taschuk <stas...@telusplanet.net> writes:

> Quoth Bernhard Herzog:
> [...]
> > Yes, but Python doesn't issue warnings about it. Actually, issuing
> > deprecation warnings for exc_traceback and friends might be a good idea.
> > The alternative has been available since 1.5 and it is a potential
> > source of bugs. It would be far less controversial than the proposed
> > syntax change for the raise statement, I think.
>
> I agree entirely, but I don't see how such warnings could be
> implemented. How can you hook into access of specific globals?

exc_* are not globals, they're attributes of the sys module.

What you could do, I think, is turn sys into an instance of a subclass
of module and make exc_traceback and friends properties in that new
subclass whose get functions simply return the appropriate value from
sys.exc_info(). That would actually solve the bug wrt. threading and the
get function could also issue a warning.

Steven Taschuk

unread,
Jun 10, 2003, 6:04:19 PM6/10/03
to
Quoth Bernhard Herzog:
> Steven Taschuk <stas...@telusplanet.net> writes:
[issuing warnings for use of sys.exc_{type, value, traceback}]

> > I agree entirely, but I don't see how such warnings could be
> > implemented. How can you hook into access of specific globals?
>
> exc_* are not globals, they're attributes of the sys module.

What's the difference between globals and module attributes?

> What you could do, I think, is turn sys into an instance of a subclass
> of module and make exc_traceback and friends properties in that new
> subclass whose get functions simply return the appropriate value from
> sys.exc_info(). That would actually solve the bug wrt. threading and the
> get function could also issue a warning.

That seems plausible -- though Guido recently reiterated on py-dev
his dislike of the idea of class-like attribute access for
modules. In his words: "When you want a class, use one. :-)".

Aahz

unread,
Jun 10, 2003, 8:35:39 PM6/10/03
to
In article <mailman.1055287253...@python.org>,

Steven Taschuk <stas...@telusplanet.net> wrote:
>
>What's the difference between globals and module attributes?

The bytecode instructions are different.

Greg Ewing (using news.cis.dfn.de)

unread,
Jun 10, 2003, 11:04:12 PM6/10/03
to
Steven Taschuk wrote:
> That seems plausible -- though Guido recently reiterated on py-dev
> his dislike of the idea of class-like attribute access for
> modules. In his words: "When you want a class, use one. :-)".

Under type/class unification, a module is already
(an instance of) a class; you just don't get any
choice about which class it's an instance of.

I've been toying with the idea of something like

__moduleclass__ = MyModuleClass

in the body of a module, somewhat analogous to
__metaclass__ in a class. The effect of this would
be that the object created by importing the module
would be an instance of the specified class, instead
of types.ModuleType.

The tricky part is that the class needs to be known
before the module object is created, but it can only
be discovered after executing (at least some of) the
module's code, and the module object needs to exist
before doing that, in case it gets imported by
something that it imports.

This could be circumvented by initially creating the
module as an ordinary module, and then later changing
its class if there is a __moduleclass__ present in its
namespace. This would probably require that the
__moduleclass__ be a subclass of types.ModuleType to
ensure C layout compatibility, but that would be fine
for the uses I have in mind.

By the way, the main use case I have for this is
for implementing autoloading of classes, so that I
can have a top-level package which apparently contains
a bunch of classes, but they don't actually get created
until someone asks for them. A module class with a
__getattr__ would be ideal for this.

I can feel a PEP coming on...

Reply all
Reply to author
Forward
0 new messages