Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign up| PEP: 3110 | |
| Title: Catching Exceptions in Python 3000 | |
| Version: $Revision$ | |
| Last-Modified: $Date$ | |
| Author: Collin Winter <collinwinter@google.com> | |
| Status: Final | |
| Type: Standards Track | |
| Content-Type: text/x-rst | |
| Created: 16-Jan-2006 | |
| Python-Version: 3.0 | |
| Post-History: | |
| Abstract | |
| ======== | |
| This PEP introduces changes intended to help eliminate ambiguities | |
| in Python's grammar, simplify exception classes, simplify garbage | |
| collection for exceptions and reduce the size of the language in | |
| Python 3.0. | |
| Rationale | |
| ========= | |
| 1. ``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>): | |
| 2. 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. | |
| 3. As specified in PEP 344 [#pep344]_, exception instances in Python 3 | |
| will possess a ``__traceback__`` attribute. The Open Issues section | |
| of that PEP includes a paragraph on garbage collection difficulties | |
| caused by this attribute, namely a "exception -> traceback -> | |
| stack frame -> exception" reference cycle, whereby all locals are | |
| kept 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 whereby the target name is deleted at the end of the | |
| ``except`` suite. | |
| 4. In the spirit of "there should be one -- and preferably only one | |
| -- obvious way to do it" [#zen]_, it is desirable to consolidate | |
| duplicate functionality. To this end, the ``exc_value``, | |
| ``exc_type`` and ``exc_traceback`` attributes of the ``sys`` | |
| module [#sys-module]_ will be removed in favor of | |
| ``sys.exc_info()``, which provides the same information. These | |
| attributes are already listed in PEP 3100 [#pep3100]_ as targeted | |
| for removal. | |
| 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. | |
| Note that the grammar above always requires parenthesized tuples as | |
| exception clases. That way, the ambiguous :: | |
| except A, B: | |
| which would mean different things in Python 2.x and 3.x -- leading to | |
| hard-to-catch bugs -- cannot legally occur in 3.x code. | |
| Semantic Changes | |
| ================ | |
| In order to resolve the garbage collection issue related to PEP 344, | |
| ``except`` statements in Python 3 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: | |
| try_body | |
| except E as N: | |
| except_body | |
| ... | |
| gets translated to (in Python 2.5 terms) :: | |
| try: | |
| try_body | |
| except E, N: | |
| try: | |
| except_body | |
| finally: | |
| N = None | |
| del N | |
| ... | |
| An implementation has already been checked into the py3k (formerly | |
| "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: | |
| ... | |
| ... | |
| becomes :: | |
| 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. | |
| Lastly, all uses of the ``sys`` module's ``exc_type``, ``exc_value`` | |
| and ``exc_traceback`` attributes will need to be removed. They can be | |
| replaced with ``sys.exc_info()[0]``, ``sys.exc_info()[1]`` and | |
| ``sys.exc_info()[2]`` respectively, a transformation that can be | |
| performed by ``2to3``'s ``sysexcattrs`` fixer. | |
| 2.6 - 3.0 Compatibility | |
| ----------------------- | |
| In order to facilitate forwards compatibility between Python 2.6 and 3.0, | |
| the ``except ... as ...:`` syntax will be backported to the 2.x series. The | |
| grammar will thus change from:: | |
| except_clause: 'except' [test [',' test]] | |
| to:: | |
| except_clause: 'except' [test [('as' | ',') test]] | |
| The end-of-suite cleanup semantic for ``except`` statements will not be | |
| included in the 2.x series of releases. | |
| Open Issues | |
| =========== | |
| Replacing or Dropping "sys.exc_info()" | |
| -------------------------------------- | |
| The idea of dropping ``sys.exc_info()`` or replacing it with a | |
| ``sys.exception`` attribute or a ``sys.get_exception()`` function | |
| has been raised several times on python-3000 ([#drop-excinfo]_, | |
| [#replace-excinfo]_) and mentioned in PEP 344's "Open Issues" section. | |
| While a ``2to3`` fixer to replace calls to ``sys.exc_info()`` | |
| and some attribute accesses would be trivial, it would be far more | |
| difficult for static analysis to find and fix functions that expect | |
| the values from ``sys.exc_info()`` as arguments. Similarly, this does | |
| not address the need to rewrite the documentation for all APIs that | |
| are defined in terms of ``sys.exc_info()``. | |
| Implementation | |
| ============== | |
| This PEP was implemented in revisions 53342 [#r53342]_ and 53349 | |
| [#r53349]_. Support for the new ``except`` syntax in 2.6 was | |
| implemented in revision 55446 [#r55446]_. | |
| References | |
| ========== | |
| .. [#pep352] | |
| http://www.python.org/dev/peps/pep-0352/ | |
| .. [#zen] | |
| http://www.python.org/dev/peps/pep-0020/ | |
| .. [#sys-module] | |
| http://docs.python.org/library/sys.html | |
| .. [#pep3100] | |
| http://www.python.org/dev/peps/pep-3100/ | |
| .. [#pep344] | |
| http://www.python.org/dev/peps/pep-0344/ | |
| .. [#firstproposal] | |
| https://mail.python.org/pipermail/python-dev/2006-March/062449.html | |
| .. [#renaming] | |
| https://mail.python.org/pipermail/python-dev/2006-March/062640.html | |
| .. [#grammar] | |
| http://docs.python.org/reference/compound_stmts.html#try | |
| .. [#except-translation] | |
| https://mail.python.org/pipermail/python-3000/2007-January/005395.html | |
| .. [#translation-checkin] | |
| http://svn.python.org/view?rev=53342&view=rev | |
| .. [#2to3] | |
| https://hg.python.org/sandbox/guido/file/2.7/Lib/lib2to3/ | |
| .. [#exceptfixer] | |
| https://hg.python.org/sandbox/guido/file/2.7/Lib/lib2to3/fixes/fix_except.py | |
| .. [#drop-excinfo] | |
| https://mail.python.org/pipermail/python-3000/2007-January/005385.html | |
| .. [#replace-excinfo] | |
| https://mail.python.org/pipermail/python-3000/2007-January/005604.html | |
| .. [#r53342] | |
| http://svn.python.org/view?view=revision&revision=53342 | |
| .. [#r53349] | |
| http://svn.python.org/view?view=revision&revision=53349 | |
| .. [#r55446] | |
| http://svn.python.org/view/python/trunk/?view=rev&rev=55446 | |
| 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: |