[Python-3000] Pre-peps on raise and except changes (was: Warning for 2.6 and greater)
Collin Winter
collinw at gmail.com
Tue Jan 23 00:27:16 CET 2007
On 1/22/07, Brett Cannon <brett at python.org> wrote:
> For the exception PEP:
>> "In addition, Python 3 will introduce a further incompatibility."
> You have not even mentioned a Py3K incompatibility yet so this
> statement is awkward.
This sentence has been cut.
> "This PEP intends to resolve this issue by adding a
> cleanup semantic to ``except`` clauses of the form ``except E as N``".
> This sentence is in reference to the cycle created with exceptions
> holding a reference to the traceback. Problem is the above gives
> absolutely no indication how a syntactic change is going to help with
> cyclic garbage collection.
I've cut the reference to the new syntax. The sentence now reads "This
PEP intends to resolve this issue by adding a cleanup semantic to
``except`` clauses in Python 3 where the target name is deleted at the
end of the ``except`` suite."
> For the raise PEP:
>> "The ease of this translation allows a further simplification of the
> language by removing the need for the ``raise E, V, T`` form.".
> At this point in the Rationale you have not explicitly stated that
> ``raise E(V)`` is going to be the only way to raise an exception.
I've cut that sentence and added this in its place:
"""
Using these translations, we can reduce the ``raise`` statement from
four forms to two:
1. ``raise`` (with no arguments) is used to re-raise the active
exception in an ``except`` suite.
2. ``raise E`` (with a single argument) is used to raise a new
exception.
"""
> You might want to also want to mention if you are or are not going to
> remove sys.exc_info . If you are then you need to state that and
> mention that all places where three arguments for exceptions is
> expected will need to be changed. Might also not hurt to reference
> any other exception information functions that are slated to go in PEP
> 3100.
I'd say that based on the number of places that will have to change
(code, documentation), dropping sys.exc_info() and friends should
probably be its own PEP. We may even want to reconsider dropping
sys.exc_info() (though sys.exc_{type, value, traceback} should go)
given the difficulty of porting.
> Thanks for doing this, Collin!
Thanks for the feedback! The latest drafts are attached.
Collin Winter
-------------- next part --------------
PEP: 310?
Title: Except Statements in Python 3000
Version: $Revision$
Last-Modified: $Date$
Author: Collin Winter <collinw at gmail.com>
Status: Draft
Type: Standards Track
Content-Type: text/x-rst
Created: 16-Jan-2006
Python-Version: 3.0
Post-History:
Abstract
========
This PEP introduces changes to ``except`` statements in Python 3.0
intended to help reduce ambiguities in Python's grammar, simplify
exception classes and simplify garbage collection for exceptions.
Rationale
=========
``except`` clauses in Python 2.x present a syntactic ambiguity where
the parser cannot differentiate whether ::
except <expression>, <expression>:
should be interpreted as ::
except <type>, <type>:
or ::
except <type>, <name>:
Python 2 opts for the latter semantic, at the cost of requiring the
former to be parenthesized, like so ::
except (<type>, <type>):
As specified in PEP 352 [#pep352]_, the ability to treat exceptions as
tuples will be removed, meaning this code will no longer work ::
except os.error, (errno, errstr):
Because the automatic unpacking will no longer be possible, it is
desirable to remove the ability to use tuples as ``except`` targets.
Both of these issues will be resolved by changing Python's grammar.
Lastly, as specified in PEP 344 [#pep344]_, Python 3 exceptions will
possess a ``__traceback__`` attribute. The Open Issues section of that
PEP includes a paragraph on garbage collection difficulties caused by
this attribute, such as a ``exception -> traceback -> stack frame
-> exception'' reference cycle, keeping all locals in scope until the
next GC run. This PEP intends to resolve this issue by adding a
cleanup semantic to ``except`` clauses in Python 3 where the target
name is deleted at the end of the ``except`` suite.
Grammar Changes
===============
In Python 3, the grammar for ``except`` statements will change
from [#grammar]_ ::
except_clause: 'except' [test [',' test]]
to ::
except_clause: 'except' [test ['as' NAME]]
The use of ``as`` in place of the comma token means that ::
except AttributeError, os.error:
can be clearly understood as a tuple of exception classes. This new
syntax was first proposed by Greg Ewing [#firstproposal]_ and
endorsed ([#firstproposal]_, [#renaming]_) by the BDFL.
Further, the restriction of the token following ``as`` from ``test``
to ``NAME`` means that only valid identifiers can be used as
``except`` targets.
Semantic Changes
================
In order to resolve the garbage collection issue related to PEP 344,
``except`` statements will generate additional bytecode to delete the
target, thus eliminating the reference cycle. The source-to-source
translation, as suggested by Phillip J. Eby [#except-translation]_ is
::
try:
...
except E as N:
...
...
is translated to ::
try:
...
except E as N:
...
N = None
del N
...
An implementation has already been checked into the p3yk branch
[#translation-checkin]_.
Compatibility Issues
====================
Nearly all ``except`` clauses will need to be changed. ``except``
clauses with identifier targets will be converted from ::
except E, N:
to ::
except E as N:
``except`` clauses with non-tuple, non-identifier targets
(e.g., ``a.b.c[d]``) will need to be converted from ::
except E, T:
to ::
except E as t:
T = t
Both of these cases can be handled by Guido van Rossum's ``2to3``
utility [#2to3]_ using the ``except`` fixer [#exceptfixer]_.
``except`` clauses with tuple targets will need to be converted
manually, on a case-by-case basis. These changes will usually need
to be accompanied by changes to the exception classes themselves.
While these changes generally cannot be automated, the ``2to3``
utility is able to point out cases where the target of an ``except``
clause is a tuple, simplifying conversion.
Situations where it is necessary to keep an exception instance around
past the end of the ``except`` suite can be easily translated like so
::
try:
...
except E as N:
...
...
is translated to ::
try:
...
except E as N:
n = N
...
...
This way, when ``N`` is deleted at the end of the block, ``n`` will
persist and can be used as normal.
References
==========
.. [#pep352]
http://www.python.org/dev/peps/pep-0352/
.. [#pep344]
http://www.python.org/dev/peps/pep-0344/
.. [#firstproposal]
http://mail.python.org/pipermail/python-dev/2006-March/062449.html
.. [#renaming]
http://mail.python.org/pipermail/python-dev/2006-March/062640.html
.. [#grammar]
http://www.python.org/doc/current/ref/try.html
.. [#except-translation]
http://mail.python.org/pipermail/python-3000/2007-January/005395.html
.. [#translation-checkin]
http://svn.python.org/view?rev=53342&view=rev
.. [#2to3]
http://svn.python.org/view/sandbox/trunk/2to3/
.. [#exceptfixer]
http://svn.python.org/view/sandbox/trunk/2to3/fixes/fix_except.py
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
coding: utf-8
End:
-------------- next part --------------
PEP: 310?
Title: Raising Exceptions in Python 3000
Version: $Revision$
Last-Modified: $Date$
Author: Collin Winter <collinw at gmail.com>
Status: Draft
Type: Standards Track
Content-Type: text/x-rst
Created: 19-Jan-2006
Python-Version: 3.0
Post-History:
Abstract
========
This PEP introduces a changes to exception raising mechanisms in
Python 3.0 intended to reduce both line noise and the size of the
language.
Rationale
=========
One of Python's guiding maxims is "There should be one -- and
preferably only one -- obvious way to do it" [#zen]_. Python 2.x's
``raise`` statement violates this principle, permitting multiple
ways of expressing the same thought. For example, these statements
are equivalent: ::
raise E, V
raise E(V)
There is a third form of the ``raise`` statement, allowing arbitrary
tracebacks to be attached to an exception [#grammar]_: ::
raise E, V, T
where T is a traceback. Note that attaching the traceback in this
manner *requires* use of the ``raise E, V`` form. As specified in
PEP 344 [#pep344]_, exception objects in Python 3.x will possess
a ``__traceback__`` attribute, admitting this translation of the
three-expression ``raise`` statement: ::
raise E, V, T
is translated to ::
e = E(V)
e.__traceback__ = T
raise e
Using these translations, we can reduce the ``raise`` statement from
four forms to two:
1. ``raise`` (with no arguments) is used to re-raise the active
exception in an ``except`` suite.
2. ``raise E`` (with a single argument) is used to raise a new
exception.
There is a further, more tangible benefit to be obtained through this
consolidation, as noted by A.M. Kuchling [#amk-line-noise]_. ::
PEP 8 doesn't express any preference between the
two forms of raise statements:
raise ValueError, 'blah'
raise ValueError("blah")
I like the second form better, because if the exception arguments
are long or include string formatting, you don't need to use line
continuation characters because of the containing parens.
The BDFL has concurred [#guido-declaration]_ and endorsed the
consolidation of the several ``raise`` forms.
Grammar Changes
===============
In Python 3, the grammar for ``raise`` statements will change
from [#grammar]_ ::
raise_stmt: 'raise' [test [',' test [',' test]]]
to ::
raise_stmt: 'raise' [test]
Other Changes
=============
Because of its relation to exception raising, the signature for the
``throw()`` method on generator objects will change, dropping the
optional second and third parameters. The signature thus changes
from [#throw-sig]_ ::
generator.throw(E, [T, [V]])
to ::
generator.throw(E)
Compatibility Issues
====================
All two- and three-expression ``raise`` statements will require
modification, as will all two- and three-expression ``throw()`` calls
on generators. Fortunately, the translation from Python 2.x to
Python 3.x in this case is simple and can be handled mechanically
by Guido van Rossum's 2to3 utility [#2to3]_ using the ``raise`` and
``throw`` fixers ([#raise-fixer]_, [#throw-fixer]_).
The following translations will be performed:
1. Zero- and one-expression ``raise`` statements will be left
intact.
2. Two-expression ``raise`` statements will be converted from ::
raise E, V
to ::
raise E(V)
Two-expression ``throw()`` calls will be converted from ::
generator.throw(E, V)
to ::
generator.throw(E(V))
3. Three-expression ``raise`` statements will be converted from ::
raise E, V, T
to ::
e = E(V)
e.__traceback__ = T
raise e
Three-expression ``throw()`` calls will be converted from ::
generator.throw(E, V, T)
to ::
e = E(V)
e.__traceback__ = T
generator.throw(e)
References
==========
.. [#zen]
http://www.python.org/dev/peps/pep-0020/
.. [#grammar]
http://www.python.org/doc/current/ref/raise.html
.. [#throw-sig]
http://www.python.org/dev/peps/pep-0342/
.. [#pep344]
http://www.python.org/dev/peps/pep-0344/
.. [#amk-line-noise]
http://mail.python.org/pipermail/python-dev/2005-August/055187.html
.. [#guido-declaration]
http://mail.python.org/pipermail/python-dev/2005-August/055190.html
.. [#2to3]
http://svn.python.org/view/sandbox/trunk/2to3/
.. [#raise-fixer]
http://svn.python.org/view/sandbox/trunk/2to3/fixes/fix_raise.py
.. [#throw-fixer]
http://svn.python.org/view/sandbox/trunk/2to3/fixes/fix_throw.py
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
coding: utf-8
End:
More information about the Python-3000
mailing list