Who should see Python deprecation warnings?
In early November, one sub-thread of a big discussion on preparing for the
Python 3.7 release focused on the await and async
identifiers. They will become keywords in 3.7, meaning that any code using
those names for any other purpose will break. Nick Coghlan observed that Python 3.6 does not warn
about the use of those names, calling it "a fairly major
oversight/bug
". In truth, though, Python 3.6 does emit
warnings in that case — but users rarely see them.
The reason for that comes down to the configuration of a relatively obscure module called warnings. The Python interpreter can generate quite a few warnings in various categories, many of which are likely to be seen as noise by users. The warnings module is used to emit warnings, but it also gives developers a way to bring back some silence by establishing a filter controlling which warnings will actually be printed out to the error stream. The default filter is:
ignore::DeprecationWarning
ignore::PendingDeprecationWarning
ignore::ImportWarning
ignore::BytesWarning
ignore::ResourceWarning
The first line filters out DeprecationWarning events, such as the warnings regarding await and async in the 3.6 release. Those warnings were also present in 3.5 as longer-term PendingDeprecationWarnings, which are also invisible by default.
As it happens, things were not always this way. While
PendingDeprecationWarning has always been filtered,
DeprecationWarning was visible by default until the
Python 2.7 and 3.2 releases. In a 2009 thread discussing the
change, Python benevolent dictator for life Guido van Rossum argued
that the deprecation warnings, while being useful to some developers, were
more often just "irrelevant noise
", especially for anybody who
does not actually work on the code in question:
The idea was fairly intensely debated, but silencing those warnings by default won out in the end.
In 2017, it has become evident that this decision has kept some important warnings out of the sight of people who should see them, with the result that many people may face an unpleasant surprise when an upgrade to 3.7 abruptly breaks previously working programs. That was the cue for a new intensely debated thread over whether deprecation warnings should be enabled again.
Neil Schemenauer started things off with a suggestion that the warnings should be re-enabled by default; Coghlan subsequently proposed reverting to the way things were. He went on to say that, if application developers don't want their users to see deprecation warnings, they should disable those warnings explicitly. The invisibility of deprecation warnings has hurt users, he said, and some classes of users in particular:
Application developers are, one hopes, using testing frameworks for their modules, and those frameworks typically turn the warnings back on. But the above-mentioned users will not be performing such testing and will be unnecessarily surprised if Python 3.7 breaks their scripts.
The proposal led to some familiar complaints, though. Van Rossum worried that it would inflict a bunch of warning noise on users of scripts who are in no position to fix them. Antoine Pitrou suggested that small-script developers would be deluged by warnings originating in modules that they import — warnings that, once again, they cannot fix. Over time, the thread seemed to coalesce on the idea that the warnings should not be re-enabled unconditionally; they should, instead, remain disabled for "third-party" code that the current user is unlikely to have control over.
That is a fine idea, with only one little problem: how does one define "third-party code" in this setting? There were a few ideas raised, such as emitting warnings for all code located under the directory containing the initial script, but the search for heuristics threatened to devolve into a set of complex special cases that nobody would be able to remember. So the solution that was written up by Coghlan as PEP 565 was rather simpler: enable DeprecationWarning in the __main__ module, while leaving it suppressed elsewhere. In essence, any code run directly by a user would have warnings enabled, while anything imported from another module would not.
This change will almost certainly not bring deprecation warnings to the attention of everybody who needs to see them. But it will cause them to be emitted for users who are running single-file scripts or typing commands directly at the Python interpreter. That solves what Coghlan sees as the biggest problem: casual Python scripters who will otherwise be unpleasantly surprised when a distribution upgrade causes their scripts to fail. It is a partial solution that appears to be better than the status quo.
Van Rossum agreed with that assessment. He
acknowledged that it's "not going to make everyone happy
", but
said that it's an improvement and that he intends to approve it in the near
future in the absence of more objections. Naturally, such a pronouncement
brought out some objections, but none of them would appear to have the
strength to keep PEP 565 from being a part of the Python 3.7
release. The 3.7 interpreter's usurpation of await and async
may be an unpleasant surprise to some users, but hopefully future
changes will be less surprising.
| Index entries for this article | |
|---|---|
| Python | Deprecation |
