[Python-Dev] PEP 565: Show DeprecationWarning in main (original) (raw)

Nick Coghlan ncoghlan at gmail.com
Sun Nov 12 04:24:12 EST 2017


I've written a short(ish) PEP for the proposal to change the default warnings filters to show DeprecationWarning in main: https://www.python.org/dev/peps/pep-0565/

The core proposal itself is just the idea in https://bugs.python.org/issue31975 (i.e. adding "default::DeprecationWarning:main" to the default filter set), but the PEP fills in some details on the motivation for the original change to the defaults, and why the current proposal is to add a new filter for main, rather than dropping the default DeprecationWarning filter entirely.

The PEP also proposes repurposing the existing FutureWarning category to explicitly mean "backwards compatibility warnings that should be shown to users of Python applications" since:

Cheers, Nick.

============== PEP: 565 Title: Show DeprecationWarning in main Author: Nick Coghlan <ncoghlan at gmail.com> Status: Draft Type: Standards Track Content-Type: text/x-rst Created: 12-Nov-2017 Python-Version: 3.7 Post-History: 12-Nov-2017

Abstract

In Python 2.7 and Python 3.2, the default warning filters were updated to hide DeprecationWarning by default, such that deprecation warnings in development tools that were themselves written in Python (e.g. linters, static analysers, test runners, code generators) wouldn't be visible to their users unless they explicitly opted in to seeing them.

However, this change has had the unfortunate side effect of making DeprecationWarning markedly less effective at its primary intended purpose: providing advance notice of breaking changes in APIs (whether in CPython, the standard library, or in third party libraries) to users of those APIs.

To improve this situation, this PEP proposes a single adjustment to the default warnings filter: displaying deprecation warnings attributed to the main module by default.

This change will mean that code entered at the interactive prompt and code in single file scripts will revert to reporting these warnings by default, while they will continue to be silenced by default for packaged code distributed as part of an importable module.

The PEP also proposes a number of small adjustments to the reference interpreter and standard library documentation to help make the warnings subsystem more approachable for new Python developers.

Specification

The current set of default warnings filters consists of::

ignore::DeprecationWarning
ignore::PendingDeprecationWarning
ignore::ImportWarning
ignore::BytesWarning
ignore::ResourceWarning

The default unittest test runner then uses warnings.catch_warnings() warnings.simplefilter('default') to override the default filters while running test cases.

The change proposed in this PEP is to update the default warning filter list to be::

default::DeprecationWarning:__main__
ignore::DeprecationWarning
ignore::PendingDeprecationWarning
ignore::ImportWarning
ignore::BytesWarning
ignore::ResourceWarning

This means that in cases where the nominal location of the warning (as determined by the stacklevel parameter to warnings.warn) is in the __main__ module, the first occurrence of each DeprecationWarning will once again be reported.

This change will lead to DeprecationWarning being displayed by default for:

While continuing to be hidden by default for:

As a result, API deprecation warnings encountered by development tools written in Python should continue to be hidden by default for users of those tools

While not its originally intended purpose, the standard library documentation will also be updated to explicitly recommend the use of FutureWarning (rather than DeprecationWarning) for backwards compatibility warnings that are intended to be seen by users of an application.

This will give the following three distinct categories of backwards compatibility warning, with three different intended audiences:

Given its presence in the standard library since Python 2.3, FutureWarning would then also have a secondary use case for libraries and frameworks that support multiple Python versions: as a more reliably visible alternative to DeprecationWarning in Python 2.7 and versions of Python 3.x prior to 3.7.

Motivation

As discussed in [1_] and mentioned in [2_], Python 2.7 and Python 3.2 changed the default handling of DeprecationWarning such that:

The intent was to avoid cases of tooling output like the following::

$ devtool mycode/
/usr/lib/python3.6/site-packages/devtool/cli.py:1:

DeprecationWarning: 'async' and 'await' will become reserved keywords in Python 3.7 async = True ... actual tool output ...

Even when devtool is a tool specifically for Python programmers, this is not a particularly useful warning, as it will be shown on every invocation, even though the main helpful step an end user can take is to report a bug to the developers of devtool. The warning is even less helpful for general purpose developer tools that are used across more languages than just Python.

However, this change proved to have unintended consequences for the following audiences:

In these cases, DeprecationWarning ended up become almost entirely equivalent to PendingDeprecationWarning: it was simply never seen at all.

Limitations on PEP Scope

This PEP exists specifically to explain both the proposed addition to the default warnings filter for 3.7, and to more clearly articulate the rationale for the original change to the handling of DeprecationWarning back in Python 2.7 and 3.2.

This PEP does not solve all known problems with the current approach to handling deprecation warnings. Most notably:

While these are real problems with the status quo, they're excluded from consideration in this PEP because they're going to require more complex solutions than a single additional entry in the default warnings filter, and resolving them at least potentially won't require going through the PEP process.

For anyone interested in pursuing them further, the first two would be unittest module enhancement requests, the third would be a warnings module enhancement request, while the last would only require a PEP if inferring API deprecations from their contents was deemed to be an intractable code analysis problem, and an explicit function and parameter marker syntax in annotations was proposed instead.

References

.. [1] stdlib-sig thread proposing the original default filter change (https://mail.python.org/pipermail/stdlib-sig/2009-November/000789.html)

.. [2] Python 2.7 notification of the default warnings filter change (https://docs.python.org/3/whatsnew/2.7.html#changes-to-the-handling-of-deprecation-warnings)

.. [3] Emitting warnings based on the location of the warning itself (https://pypi.org/project/warn/)

Copyright

This document has been placed in the public domain.

-- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia



More information about the Python-Dev mailing list