Movatterモバイル変換


[0]ホーム

URL:


[Python-Dev] PEP 565: Show DeprecationWarning in __main__

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


I've written a short(ish) PEP for the proposal to change the defaultwarnings filters to show DeprecationWarning in __main__:https://www.python.org/dev/peps/pep-0565/The core proposal itself is just the idea inhttps://bugs.python.org/issue31975 (i.e. adding"default::DeprecationWarning:__main__" to the default filter set), butthe PEP fills in some details on the motivation for the originalchange to the defaults, and why the current proposal is to add a newfilter for __main__, rather than dropping the defaultDeprecationWarning filter entirely.The PEP also proposes repurposing the existing FutureWarning categoryto explicitly mean "backwards compatibility warnings that should beshown to users of Python applications" since:- we don't tend to use FutureWarning for its original nominal purpose(changes that will continue to run but will do something different)- FutureWarning was added in 2.3, so it's available in all stillsupported versions of Python, and is shown by default in all of them- it's at least arguably a less-jargony spelling ofDeprecationWarning, and hence more appropriate for displaying to endusers that may not have encountered the specific notion of "APIdeprecation"Cheers,Nick.==============PEP: 565Title: Show DeprecationWarning in __main__Author: Nick Coghlan <ncoghlan at gmail.com>Status: DraftType: Standards TrackContent-Type: text/x-rstCreated: 12-Nov-2017Python-Version: 3.7Post-History: 12-Nov-2017Abstract========In Python 2.7 and Python 3.2, the default warning filters were updated to hideDeprecationWarning by default, such that deprecation warnings in developmenttools that were themselves written in Python (e.g. linters, static analysers,test runners, code generators) wouldn't be visible to their users unless theyexplicitly opted in to seeing them.However, this change has had the unfortunate side effect of makingDeprecationWarning markedly less effective at its primary intended purpose:providing advance notice of breaking changes in APIs (whether in CPython, thestandard library, or in third party libraries) to users of those APIs.To improve this situation, this PEP proposes a single adjustment to thedefault warnings filter: displaying deprecation warnings attributed to the mainmodule by default.This change will mean that code entered at the interactive prompt and code insingle file scripts will revert to reporting these warnings by default, whilethey will continue to be silenced by default for packaged code distributed aspart of an importable module.The PEP also proposes a number of small adjustments to the referenceinterpreter and standard library documentation to help make the warningssubsystem 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::ResourceWarningThe default ``unittest`` test runner then uses ``warnings.catch_warnings()````warnings.simplefilter('default')`` to override the default filters whilerunning test cases.The change proposed in this PEP is to update the default warning filter listto be::    default::DeprecationWarning:__main__    ignore::DeprecationWarning    ignore::PendingDeprecationWarning    ignore::ImportWarning    ignore::BytesWarning    ignore::ResourceWarningThis means that in cases where the nominal location of the warning (asdetermined by the ``stacklevel`` parameter to ``warnings.warn``) is in the``__main__`` module, the first occurrence of each DeprecationWarning will onceagain be reported.This change will lead to DeprecationWarning being displayed by default for:* code executed directly at the interactive prompt* code executed directly as part of a single-file scriptWhile continuing to be hidden by default for:* code imported from another module in a ``zipapp`` archive's ``__main__.py``  file* code imported from another module in an executable package's ``__main__``  submodule* code imported from an executable script wrapper generated at installation time  based on a ``console_scripts`` or ``gui_scripts`` entry point definitionAs a result, API deprecation warnings encountered by development tools writtenin Python should continue to be hidden by default for users of those toolsWhile not its originally intended purpose, the standard library documentationwill also be updated to explicitly recommend the use of``FutureWarning`` (ratherthan ``DeprecationWarning``) for backwards compatibility warnings that areintended to be seen by *users* of an application.This will give the following three distinct categories of backwardscompatibility warning, with three different intended audiences:* ``PendingDeprecationWarning``: reported by default only in test runners that  override the default set of warning filters. The intended audience is Python  developers that take an active interest in ensuring the future compatibility  of their software (e.g. professional Python application developers with  specific support obligations).* ``DeprecationWarning``: reported by default for code that runs directly in  the ``__main__`` module (as such code is considered relatively unlikely to  have a dedicated test suite), but relies on test suite based reporting for  code in other modules. The intended audience is Python developers that are at  risk of upgrades to their dependencies (including upgrades to Python itself)  breaking their software (e.g. developers using Python to script environments  where someone else is in control of the timing of dependency upgrades).* ``FutureWarning``: always reported by default. The intended audience is users  of applications written in Python, rather than other Python developers  (e.g. warning about use of a deprecated setting in a configuration file  format).Given its presence in the standard library since Python 2.3, ``FutureWarning``would then also have a secondary use case for libraries and frameworks thatsupport 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 changedthe default handling of ``DeprecationWarning`` such that:* the warning was hidden by default during normal code execution* the `unittest`` test runner was updated to re-enable it when running testsThe 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 keywordsin Python 3.7      async = True    ... actual tool output ...Even when `devtool` is a tool specifically for Python programmers, this is nota particularly useful warning, as it will be shown on every invocation, eventhough the main helpful step an end user can take is to report a bug to thedevelopers of ``devtool``. The warning is even less helpful for general purposedeveloper tools that are used across more languages than just Python.However, this change proved to have unintended consequences for the followingaudiences:* anyone using a test runner other than the default one built into ``unittest``  (since the request for third party test runners to change their default  warnings filters was never made explicitly)* anyone using the default ``unittest`` test runner to test their Python code  in a subprocess (since even ``unittest`` only adjusts the warnings settings  in the current process)* anyone writing Python code at the interactive prompt or as part of a directly  executed script that didn't have a Python level test suite at allIn these cases, ``DeprecationWarning`` ended up become almost entirelyequivalent to ``PendingDeprecationWarning``: it was simply never seen at all.Limitations on PEP Scope========================This PEP exists specifically to explain both the proposed addition to thedefault warnings filter for 3.7, *and* to more clearly articulate the rationalefor the original change to the handling of DeprecationWarning back in Python 2.7and 3.2.This PEP does not solve all known problems with the current approach to handlingdeprecation warnings. Most notably:* the default ``unittest`` test runner does not currently report deprecation  warnings emitted at module import time, as the warnings filteroverride is only  put in place during test execution, not during test discovery and loading.* the default ``unittest`` test runner does not currently report deprecation  warnings in subprocesses, as the warnings filter override is applied directly  to the loaded ``warnings`` module, not to the ``PYTHONWARNINGS`` environment  variable.* the standard library doesn't provide a straightforward way to opt-in to seeing  all warnings emitted *by* a particular dependency prior to upgrading it  (the third-party ``warn`` module [3_] does provide this, but enabling it  involves monkeypatching the standard library's ``warnings`` module).* re-enabling deprecation warnings by default in __main__ doesn't help in  handling cases where software has been factored out into support modules, but  those modules still have little or no automated test coverage. Near term, the  best currently available answer is to run such applications with  ``PYTHONWARNINGS=default::DeprecationWarning`` or  ``python -W default::DeprecationWarning`` and pay attention to their  ``stderr`` output. Longer term, this is really a question for researchers  working on static analysis of Python code: how to reliably find usage of  deprecated APIs, and how to infer that an API or parameter is deprecated  based on ``warnings.warn`` calls, without actually running either the code  providing the API or the code accessing itWhile these are real problems with the status quo, they're excluded fromconsideration in this PEP because they're going to require more complexsolutions than a single additional entry in the default warnings filter,and resolving them at least potentially won't require going through the PEPprocess.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 ifinferring API deprecations from their contents was deemed to be an intractablecode analysis problem, and an explicit function and parameter marker syntax inannotations 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-Devmailing list

[8]ページ先頭

©2009-2025 Movatter.jp