Skip to content

Commit d923f34

Browse files
authored
Docs page on filtering warnings (#5509)
* Docs page on filtering warnings. * What's New entry. * Warnings doctest relative path. * Corrections to command line warning filtering. * Typo.
1 parent f054047 commit d923f34

File tree

3 files changed

+274
-1
lines changed

3 files changed

+274
-1
lines changed
Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
.. _filtering-warnings:
2+
3+
==================
4+
Filtering Warnings
5+
==================
6+
7+
Since Iris cannot predict your specific needs, it by default raises Warnings
8+
for anything that might be a problem for **any** user, and is designed to work with
9+
you to ``ignore`` Warnings which you do not find helpful.
10+
11+
.. testsetup:: filtering_warnings
12+
13+
from pathlib import Path
14+
import sys
15+
import warnings
16+
17+
import iris
18+
import iris.coord_systems
19+
import iris.exceptions
20+
21+
# Hack to ensure doctests actually see Warnings that are raised, and that
22+
# they have a relative path (so a test pass is not machine-dependent).
23+
warnings.filterwarnings("default")
24+
IRIS_FILE = Path(iris.__file__)
25+
def custom_warn(message, category, filename, lineno, file=None, line=None):
26+
filepath = Path(filename)
27+
filename = str(filepath.relative_to(IRIS_FILE.parents[1]))
28+
sys.stdout.write(warnings.formatwarning(message, category, filename, lineno))
29+
warnings.showwarning = custom_warn
30+
31+
geog_cs_globe = iris.coord_systems.GeogCS(6400000)
32+
orthographic_coord_system = iris.coord_systems.Orthographic(
33+
longitude_of_projection_origin=0,
34+
latitude_of_projection_origin=0,
35+
ellipsoid=geog_cs_globe,
36+
)
37+
38+
39+
def my_operation():
40+
geog_cs_globe.inverse_flattening = 0.1
41+
_ = orthographic_coord_system.as_cartopy_crs()
42+
43+
Here is a hypothetical operation - ``my_operation()`` - which raises two
44+
Warnings:
45+
46+
.. doctest:: filtering_warnings
47+
48+
>>> my_operation()
49+
...
50+
iris/coord_systems.py:454: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance.
51+
warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning)
52+
iris/coord_systems.py:821: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy.
53+
warnings.warn(
54+
55+
Warnings can be suppressed using the Python warnings filter with the ``ignore``
56+
action. Detailed information is available in the Python documentation:
57+
:external+python:mod:`warnings`.
58+
59+
The key points are:
60+
61+
- :ref:`When<warning-filter-application>`: a warnings filter can be applied
62+
either from the command line or from within Python.
63+
- :ref:`What<warning-filter-specificity>`: a warnings filter accepts
64+
various arguments to specify which Warnings are being filtered. Both broad
65+
and narrow filters are possible.
66+
67+
.. _warning-filter-application:
68+
69+
**When** a Warnings Filter can be Applied
70+
-----------------------------------------
71+
72+
- **Command line:** setting the :external+python:envvar:`PYTHONWARNINGS`
73+
environment variable.
74+
- **Command line:** the `python -W <https://docs.python.org/3/using/cmdline.html#cmdoption-W>`_
75+
command line argument.
76+
- **Within Python:** use :func:`warnings.filterwarnings` .
77+
78+
The :ref:`warning-filter-specificity` section demonstrates using
79+
:func:`warnings.filterwarnings`, and shows the equivalent **command line**
80+
approaches.
81+
82+
83+
.. _warning-filter-specificity:
84+
85+
**What** Warnings will be Filtered
86+
----------------------------------
87+
88+
.. note::
89+
90+
For all of these examples we are using the
91+
:class:`~warnings.catch_warnings` context manager to ensure any changes to
92+
settings are temporary.
93+
94+
This should always work fine for the ``ignore``
95+
warning filter action, but note that some of the other actions
96+
may not behave correctly with all Iris operations, as
97+
:class:`~warnings.catch_warnings` is not thread-safe (e.g. using the
98+
``once`` action may cause 1 warning per chunk of lazy data).
99+
100+
Specific Warnings
101+
~~~~~~~~~~~~~~~~~
102+
103+
**When you do not want a specific warning, but still want all others.**
104+
105+
You can target specific Warning messages, e.g.
106+
107+
.. doctest:: filtering_warnings
108+
109+
>>> with warnings.catch_warnings():
110+
... warnings.filterwarnings("ignore", message="Discarding false_easting")
111+
... my_operation()
112+
...
113+
iris/coord_systems.py:454: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance.
114+
warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning)
115+
116+
::
117+
118+
python -W ignore:"Discarding false_easting"
119+
export PYTHONWARNINGS=ignore:"Discarding false_easting"
120+
121+
----
122+
123+
Or you can target Warnings raised by specific lines of specific modules, e.g.
124+
125+
.. doctest:: filtering_warnings
126+
127+
>>> with warnings.catch_warnings():
128+
... warnings.filterwarnings("ignore", module="iris.coord_systems", lineno=454)
129+
... my_operation()
130+
...
131+
iris/coord_systems.py:821: IrisDefaultingWarning: Discarding false_easting and false_northing that are not used by Cartopy.
132+
warnings.warn(
133+
134+
::
135+
136+
python -W ignore:::iris.coord_systems:454
137+
export PYTHONWARNINGS=ignore:::iris.coord_systems:454
138+
139+
Warnings from a Common Source
140+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
141+
142+
**When you do not want ANY warnings raised by a module, or collection of
143+
modules.**
144+
145+
E.g. filtering the ``coord_systems`` module:
146+
147+
.. doctest:: filtering_warnings
148+
149+
>>> with warnings.catch_warnings():
150+
... warnings.filterwarnings("ignore", module="iris.coord_systems")
151+
... my_operation()
152+
153+
::
154+
155+
python -W ignore:::iris.coord_systems
156+
export PYTHONWARNINGS=ignore:::iris.coord_systems
157+
158+
----
159+
160+
If using :func:`warnings.filterwarnings` , you can also use partial
161+
definitions. The below example will ``ignore`` all Warnings from ``iris`` as a
162+
whole.
163+
164+
.. doctest:: filtering_warnings
165+
166+
>>> with warnings.catch_warnings():
167+
... warnings.filterwarnings("ignore", module="iris")
168+
... my_operation()
169+
170+
The above 'partial' filter is not available with the command line approaches.
171+
172+
Warnings of a Common Type
173+
~~~~~~~~~~~~~~~~~~~~~~~~~
174+
175+
**When you do not want any Warnings of the same nature, from anywhere in the
176+
code you are calling.**
177+
178+
The below example will ``ignore`` any
179+
:class:`~iris.exceptions.IrisDefaultingWarning` that gets raised by *any*
180+
module during execution:
181+
182+
.. doctest:: filtering_warnings
183+
184+
>>> with warnings.catch_warnings():
185+
... warnings.filterwarnings(
186+
... "ignore",
187+
... category=iris.exceptions.IrisDefaultingWarning
188+
... )
189+
... my_operation()
190+
...
191+
iris/coord_systems.py:454: IrisUserWarning: Setting inverse_flattening does not affect other properties of the GeogCS object. To change other properties set them explicitly or create a new GeogCS instance.
192+
warnings.warn(wmsg, category=iris.exceptions.IrisUserWarning)
193+
194+
----
195+
196+
Using :class:`~iris.exceptions.IrisUserWarning` in the filter will ``ignore``
197+
both Warnings, since :class:`~iris.exceptions.IrisDefaultingWarning` subclasses
198+
:class:`~iris.exceptions.IrisUserWarning` :
199+
200+
.. doctest:: filtering_warnings
201+
202+
>>> with warnings.catch_warnings():
203+
... warnings.filterwarnings(
204+
... "ignore",
205+
... category=iris.exceptions.IrisUserWarning
206+
... )
207+
... my_operation()
208+
209+
----
210+
211+
The command line approaches can only handle the built-in Warning
212+
categories (`cpython#66733`_)::
213+
214+
python -W ignore::UserWarning
215+
export PYTHONWARNINGS=ignore::UserWarning
216+
217+
----
218+
219+
There are several built-in Python warning categories that can be used here
220+
(:class:`DeprecationWarning` being a popular example, see
221+
:external+python:mod:`warnings` for more). Since Iris has
222+
so many different warnings that might be raised, Iris subclasses
223+
:class:`UserWarning` to :class:`~iris.exceptions.IrisUserWarning`, which itself
224+
has **many** specialised subclasses. These subclasses exist to give you more
225+
granularity in your warning filtering; you can see the full list by
226+
searching the :mod:`iris.exceptions` page for ``warning`` .
227+
228+
.. attention::
229+
230+
If you have ideas for adding/altering Iris' warning categories, please
231+
:ref:`get in touch<development_where_to_start>`! The categories exist to
232+
make your life easier, and it is simple to make modifications.
233+
234+
235+
More Detail
236+
-----------
237+
238+
Different people use Iris for very different purposes, from quick file
239+
visualisation to extract-transform-load to statistical analysis. These
240+
contrasting priorities mean disagreement on which Iris problems can be ignored
241+
and which are critically important.
242+
243+
For problems that prevent Iris functioning: **Concrete Exceptions** are raised, which
244+
stop code from running any further - no debate here. For less catastrophic
245+
problems: **Warnings** are raised,
246+
which notify you (in ``stderr``) but allow code to continue running. The Warnings are
247+
there because Iris may **OR may not** function in the way you expect,
248+
depending on what you need - e.g. a problem might prevent data being saved to
249+
NetCDF, but statistical analysis will still work fine.
250+
251+
Examples of Iris Warnings
252+
~~~~~~~~~~~~~~~~~~~~~~~~~
253+
254+
- If you attempt to plot un-bounded point data as a ``pcolormesh``: Iris will
255+
guess appropriate bounds around each point so that quadrilaterals can be
256+
plotted. This permanently modifies the relevant coordinates, so the you are
257+
warned in case downstream operations assume un-bounded coordinates.
258+
- If you load a NetCDF file where a CF variable references another variable -
259+
e.g. ``my_var:coordinates = "depth_var" ;`` - but the referenced variable
260+
(``depth_var``) is not in the file: Iris will still construct
261+
its data model, but without this reference relationship. You are warned since
262+
the file includes an error and the loaded result might therefore not be as
263+
expected.
264+
265+
266+
.. testcleanup:: filtering_warnings
267+
268+
warnings.filterwarnings("ignore")
269+
270+
271+
.. _cpython#66733: https://github.com/python/cpython/issues/66733

docs/src/userguide/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ they may serve as a useful reference for future exploration.
4242
:maxdepth: 2
4343
:caption: Further Topics
4444

45+
../further_topics/filtering_warnings
4546
../further_topics/metadata
4647
../further_topics/lenient_metadata
4748
../further_topics/lenient_maths

docs/src/whatsnew/latest.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ This document explains the changes made to Iris for this release
7272
📚 Documentation
7373
================
7474

75-
#. N/A
75+
#. `@trexfeathers`_ documented the intended use of warnings filtering with
76+
Iris. See :ref:`filtering-warnings`. (:pull:`5509`)
7677

7778

7879
💼 Internal

0 commit comments

Comments
 (0)