DeprecationWarning is now silent by default.

This was originally suggested by Guido, discussed on the stdlib-sig mailing
list, and given the OK by Guido directly to me. What this change essentially
means is that Python has taken a policy of silencing warnings that are only
of interest to developers by default. This should prevent users from seeing
warnings which are triggered by an application being run against a new
interpreter before the app developer has a chance to update their code.

Closes issue #7319. Thanks to Antoine Pitrou, Ezio Melotti, and Brian Curtin
for helping with the issue.
This commit is contained in:
Brett Cannon 2010-01-10 02:56:19 +00:00
parent 3ad57e2625
commit 6fdd3dcb6a
6 changed files with 65 additions and 31 deletions

View File

@ -59,7 +59,7 @@ following warnings category classes are currently defined:
| :exc:`UserWarning` | The default category for :func:`warn`. |
+----------------------------------+-----------------------------------------------+
| :exc:`DeprecationWarning` | Base category for warnings about deprecated |
| | features. |
| | features (ignored by default). |
+----------------------------------+-----------------------------------------------+
| :exc:`SyntaxWarning` | Base category for warnings about dubious |
| | syntactic features. |
@ -89,6 +89,9 @@ User code can define additional warning categories by subclassing one of the
standard warning categories. A warning category must always be a subclass of
the :exc:`Warning` class.
.. versionchanged:: 2.7
:exc:`DeprecationWarning` is ignored by default.
.. _warning-filter:
@ -148,14 +151,6 @@ interpreter command line. The interpreter saves the arguments for all
:mod:`warnings` module parses these when it is first imported (invalid options
are ignored, after printing a message to ``sys.stderr``).
The warnings that are ignored by default may be enabled by passing :option:`-Wd`
to the interpreter. This enables default handling for all warnings, including
those that are normally ignored by default. This is particular useful for
enabling ImportWarning when debugging problems importing a developed package.
ImportWarning can also be enabled explicitly in Python code using::
warnings.simplefilter('default', ImportWarning)
.. _warning-suppress:
@ -226,6 +221,37 @@ continues to increase after each operation, or else delete the previous
entries from the warnings list before each new operation).
Updating Code For New Versions of Python
----------------------------------------
Warnings that are only of interest to the developer are ignored by default. As
such you should make sure to test your code with typically ignored warnings
made visible. You can do this from the command-line by passing :option:`-Wd`
to the interpreter (this is shorthand for :option:`-W default`). This enables
default handling for all warnings, including those that are ignored by default.
To change what action is taken for encountered warnings you simply change what
argument is passed to :option:`-W`, e.g. :option:`-W error`. See the
:option:`-W` flag for more details on what is possible.
To programmatically do the same as :option:`-Wd`, use::
warnings.simplefilter('default')
Make sure to execute this code as soon as possible. This prevents the
registering of what warnings have been raised from unexpectedly influencing how
future warnings are treated.
Having certain warnings ignored by default is done to prevent a user from
seeing warnings that are only of interest to the developer. As you do not
necessarily have control over what interpreter a user uses to run their code,
it is possible that a new version of Python will be released between your
release cycles. The new interpreter release could trigger new warnings in your
code that were not there in an older interpreter, e.g.
:exc:`DeprecationWarning` for a module that you are using. While you as a
developer want to be notified that your code is using a deprecated module, to a
user this information is essentially noise and provides no benefit to them.
.. _warning-functions:
Available Functions

View File

@ -4,6 +4,7 @@
import unittest
from test_support import check_warnings, run_unittest, cpython_only
import warnings
class FormatDeprecationTests(unittest.TestCase):
@ -17,6 +18,7 @@ class FormatDeprecationTests(unittest.TestCase):
buf = create_string_buffer(' ' * 100)
with check_warnings() as w:
warnings.simplefilter('default')
PyOS_ascii_formatd(byref(buf), sizeof(buf), '%+.10f',
c_double(10.0))
self.assertEqual(buf.value, '+10.0000000000')

View File

@ -309,6 +309,7 @@ class ExceptionTests(unittest.TestCase):
# BaseException.__init__ triggers a deprecation warning.
exc = BaseException("foo")
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('default')
self.assertEquals(exc.message, "foo")
self.assertEquals(len(w), 1)
self.assertEquals(w[0].category, DeprecationWarning)

View File

@ -383,8 +383,8 @@ except ImportError:
# Module initialization
_processoptions(sys.warnoptions)
if not _warnings_defaults:
simplefilter("ignore", category=PendingDeprecationWarning, append=1)
simplefilter("ignore", category=ImportWarning, append=1)
for cls in (DeprecationWarning, PendingDeprecationWarning, ImportWarning):
simplefilter("ignore", category=cls, append=True)
bytes_warning = sys.flags.bytes_warning
if bytes_warning > 1:
bytes_action = "error"

View File

@ -12,6 +12,8 @@ What's New in Python 2.7 alpha 3?
Core and Builtins
-----------------
- Issue #7319: Silence DeprecationWarning by default.
- Issue #2335: Backport set literals syntax from Python 3.x.
Library

View File

@ -85,10 +85,10 @@ get_default_action(void)
default_action = get_warnings_attr("defaultaction");
if (default_action == NULL) {
if (PyErr_Occurred()) {
return NULL;
}
return _default_action;
if (PyErr_Occurred()) {
return NULL;
}
return _default_action;
}
Py_DECREF(_default_action);
@ -202,12 +202,12 @@ normalize_module(PyObject *filename)
mod_str = PyString_AsString(filename);
if (mod_str == NULL)
return NULL;
return NULL;
len = PyString_Size(filename);
if (len < 0)
return NULL;
if (len >= 3 &&
strncmp(mod_str + (len - 3), ".py", 3) == 0) {
strncmp(mod_str + (len - 3), ".py", 3) == 0) {
module = PyString_FromStringAndSize(mod_str, len-3);
}
else {
@ -251,7 +251,7 @@ show_warning(PyObject *filename, int lineno, PyObject *text, PyObject
name = PyObject_GetAttrString(category, "__name__");
if (name == NULL) /* XXX Can an object lack a '__name__' attribute? */
return;
return;
f_stderr = PySys_GetObject("stderr");
if (f_stderr == NULL) {
@ -341,7 +341,7 @@ warn_explicit(PyObject *category, PyObject *message,
rc = already_warned(registry, key, 0);
if (rc == -1)
goto cleanup;
else if (rc == 1)
else if (rc == 1)
goto return_none;
/* Else this warning hasn't been generated before. */
}
@ -492,9 +492,9 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
/* Setup filename. */
*filename = PyDict_GetItemString(globals, "__file__");
if (*filename != NULL) {
Py_ssize_t len = PyString_Size(*filename);
Py_ssize_t len = PyString_Size(*filename);
const char *file_str = PyString_AsString(*filename);
if (file_str == NULL || (len < 0 && PyErr_Occurred()))
if (file_str == NULL || (len < 0 && PyErr_Occurred()))
goto handle_error;
/* if filename.lower().endswith((".pyc", ".pyo")): */
@ -506,10 +506,10 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
tolower(file_str[len-1]) == 'o'))
{
*filename = PyString_FromStringAndSize(file_str, len-1);
if (*filename == NULL)
goto handle_error;
}
else
if (*filename == NULL)
goto handle_error;
}
else
Py_INCREF(*filename);
}
else {
@ -536,8 +536,8 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno,
else {
/* embedded interpreters don't have sys.argv, see bug #839151 */
*filename = PyString_FromString("__main__");
if (*filename == NULL)
goto handle_error;
if (*filename == NULL)
goto handle_error;
}
}
if (*filename == NULL) {
@ -839,26 +839,29 @@ create_filter(PyObject *category, const char *action)
static PyObject *
init_filters(void)
{
PyObject *filters = PyList_New(3);
PyObject *filters = PyList_New(4);
const char *bytes_action;
if (filters == NULL)
return NULL;
PyList_SET_ITEM(filters, 0,
create_filter(PyExc_DeprecationWarning, "ignore"));
PyList_SET_ITEM(filters, 1,
create_filter(PyExc_PendingDeprecationWarning, "ignore"));
PyList_SET_ITEM(filters, 1, create_filter(PyExc_ImportWarning, "ignore"));
PyList_SET_ITEM(filters, 2, create_filter(PyExc_ImportWarning, "ignore"));
if (Py_BytesWarningFlag > 1)
bytes_action = "error";
else if (Py_BytesWarningFlag)
bytes_action = "default";
else
bytes_action = "ignore";
PyList_SET_ITEM(filters, 2, create_filter(PyExc_BytesWarning,
PyList_SET_ITEM(filters, 3, create_filter(PyExc_BytesWarning,
bytes_action));
if (PyList_GET_ITEM(filters, 0) == NULL ||
PyList_GET_ITEM(filters, 1) == NULL ||
PyList_GET_ITEM(filters, 2) == NULL) {
PyList_GET_ITEM(filters, 2) == NULL ||
PyList_GET_ITEM(filters, 3) == NULL) {
Py_DECREF(filters);
return NULL;
}