Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PEP 760: No more bare excepts #4015

Merged
merged 7 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ peps/pep-0756.rst @vstinner
peps/pep-0757.rst @vstinner
peps/pep-0758.rst @pablogsal @brettcannon
peps/pep-0789.rst @njsmith
peps/pep-0760.rst @pablogsal @brettcannon
# ...
peps/pep-0801.rst @warsaw
# ...
Expand Down
162 changes: 162 additions & 0 deletions peps/pep-0760.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
PEP: 760
Title: No More Bare Excepts
Author: Pablo Galindo <[email protected]>, Brett Cannon <[email protected]>
PEP-Delegate: TBD
Status: Draft
Type: Standards Track
Created: 30-Sep-2024
Python-Version: 3.14


Abstract
========

This PEP proposes disallowing bare ``except:`` clauses in Python's
exception-handling syntax. Currently, Python allows catching all exceptions
with a bare ``except:`` clause, which can lead to overly broad exception
handling and mask important errors. This PEP suggests requiring explicit
exception types in all except clauses, promoting more precise and intentional
error handling.


Motivation
==========

The current syntax allows for catching all exceptions with a bare ``except:`` clause is:

.. code-block:: python

try:
risky_operation()
except:
handle_any_error()

While this syntax can be convenient for a "catch all" handler, it often leads
to poor coding practices:

1. It can mask important errors that should be propagated.
2. It makes debugging more difficult by catching and potentially hiding
unexpected exceptions.
3. It goes against the Python principle of explicit over implicit.

Various linters [1]_ [2]_ [3]_ and style guides (including :pep:`8`) [4]_ [5]_
[6]_ [7]_ discourage bare ``except`` clauses.

By requiring explicit exception types, we can encourage more thoughtful and
precise error handling:

.. code-block:: python

try:
risky_operation()
except Exception as e:
handle_expected_error(e)


Rationale
=========

The decision to disallow bare except clauses is based on the following
considerations:

1. Requiring specific exception types makes the programmer's intentions clear
and encourages thinking about what exceptions might occur.

2. Catching only specific exceptions makes identifying and debugging unexpected
errors easier.

3. Preventing overly broad exception handling reduces the risk of silently
ignoring critical errors.

4. Many style guides and linters already discourage the use of bare except
clauses.


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

The syntax for the except clause will be modified to require an exception type.
The grammar will be updated to remove the possibility of adding an empty
expression in except clauses.

This change disallows the bare 'except:' syntax. All except clauses must
specify at least one exception type:

.. code-block:: python

try:
...
except ValueError:
...
except (TypeError, RuntimeError):
...
except Exception:
... # Still allowed, but catches all exceptions explicitly

The semantics of exception handling remain unchanged, except that it will no
longer be possible to catch all exceptions without explicitly specifying
'Exception' or a similarly broad exception type.


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

This change is not backwards compatible. Existing code that uses bare 'except:'
clauses will need to be modified. To ease the transition:

1. A deprecation warning will be issued for bare except clauses in Python 3.14.
2. The syntax will be fully disallowed in Python 3.15.

A tool will be provided to automatically update code to replace bare 'except:'
with 'except Exception:'.


Security Implications
=====================

This change has no security implications.


How to Teach This
=================

For new Python users, exception handling should be taught with explicit
exception types from the start:

.. code-block:: python

try:
result = risky_operation()
except ValueError:
handle_value_error()
except TypeError:
handle_type_error()
except Exception as e:
handle_unexpected_error(e)

For experienced users, the change can be introduced as a best practice that is
now enforced by the language. The following points should be emphasized:

1. Always catch specific exceptions when possible.
2. Use ``except Exception:`` as a last resort for truly unexpected errors.
3. Never silence exceptions without careful consideration.

Documentation should guide common exception hierarchies and how to choose
appropriate exception types to catch.


Copyright
=========

This document is placed in the public domain or under the
CC0-1.0-Universal license, whichever is more permissive.

.. [1] https://pylint.pycqa.org/en/latest/user_guide/messages/warning/bare-except.html
.. [2] https://www.flake8rules.com/rules/E722.html
.. [3] https://docs.astral.sh/ruff/rules/bare-except/
.. [4] https://google.github.io/styleguide/pyguide.html#24-exceptions
.. [5] https://chromium.googlesource.com/chromiumos/platform/factory/+/HEAD/CODING_STYLE.md#Avoid-bare_except
.. [6] https://4.docs.plone.org/develop/plone-coredev/style.html#concrete-rules
.. [7] https://docs.openedx.org/en/latest/developers/references/developer_guide/style_guides/python-guidelines.html