Capture warnings#

pytask captures warnings during the execution.

Here is an example with the most infamous warning in the world of scientific Python.

from pathlib import Path

import pandas as pd
from pytask import Product
from typing_extensions import Annotated


def _create_df() -> pd.DataFrame:
    df = pd.DataFrame({"a": range(10), "b": range(10, 20)})
    df[df["a"] < 5]["b"] = 1
    return df


def task_warning(path: Annotated[Path, Product] = Path("df.pkl")) -> None:
    df = _create_df()
    df.to_pickle(path)

Running pytask produces

$ pytask
──────────────────────────── Start pytask session ────────────────────────────
Platform: win32 -- Python <span style="color: var(--termynal-blue)">3.10.0</span>, pytask <span style="color: var(--termynal-blue)">0.4.0</span>, pluggy <span style="color: var(--termynal-blue)">1.0.0</span>
Root: C:\Users\pytask-dev\git\my_project
Collected <span style="color: var(--termynal-blue)">1</span> task.

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Task                                              ┃ Outcome ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ <span class="termynal-dim">task_warning.py::</span>task_warning                     │ <span class="termynal-success">.</span>       │
└───────────────────────────────────────────────────┴─────────┘

<span class="termynal-dim">──────────────────────────────────────────────────────────────────────────────</span>
<span class="termynal-success">╭───────────</span> <span style="font-weight: bold;">Summary</span> <span class="termynal-success">────────────╮</span>
<span class="termynal-success">│</span> <span style="font-weight: bold;"> 1  Collected tasks </span>           <span class="termynal-success">│</span>
<span class="termynal-success">│</span> <span class="termynal-success-textonly"> 1  Succeeded        (100.0%) </span> <span class="termynal-success">│</span>
<span class="termynal-success">╰────────────────────────────────╯</span>
<span class="termynal-success">───────────────────────── Succeeded in 0.24 seconds ──────────────────────────</span>
<span class="termynal-skipped">╭───────────────────────────────── Warnings ─────────────────────────────────╮</span>
<span class="termynal-skipped">│ task_warning.py::task_warning                                              │</span>
<span class="termynal-skipped">│     ...\my_project\task_warning.py:8: SettingWithCopyWarning:              │</span>
<span class="termynal-skipped">│     A value is trying to be set on a copy of a slice from a DataFrame.     │</span>
<span class="termynal-skipped">│     Try using .loc = value instead                                         │</span>
<span class="termynal-skipped">│                                                                            │</span>
<span class="termynal-skipped">│     See the caveats in the documentation:                                  │</span>
<span class="termynal-skipped">│     https://pandas.pydata.org/pandas-docs/stable/user_guide/               │</span>
<span class="termynal-skipped">│     indexing.html#returning-a-view-versus-a-copy                           │</span>
<span class="termynal-skipped">│       df[df[&quot;a&quot;] &lt; 5][&quot;b&quot;] = 1                                             │</span>
<span class="termynal-skipped">│                                                                            │</span>
<span class="termynal-skipped">│ </span><font color="#cd3131">♥</font><span class="termynal-skipped"> https://pytask-dev.rtfd.io/en/stable/how_to_guides/capture_warnings.html │</span>
<span class="termynal-skipped">╰────────────────────────────────────────────────────────────────────────────╯</span>

Controlling warnings#

You can use the filterwarnings option in pyproject.toml to configure pytask’s behavior when it comes to warnings.

The syntax for specifying warnings filters is the same as in the Python standard library, i.e., a sequence of fields separated by colons:

action:message:category:module:line

You can specify a list of such filters. When a warning matches more than one option, the action for the last matching option is performed.

For example, the configuration below will ignore specific deprecation warnings matching a regex, all user warnings, and transform all other warnings into errors.

[tool.pytask.ini_options]
filterwarnings = [
    "error",
    "ignore::UserWarning",
    # note the use of single quote below to denote "raw" strings in TOML
    'ignore:function ham\(\) is deprecated:DeprecationWarning',
]

The syntax is explained in more detail in this section of the Python documentation and there are also more examples.

@pytask.mark.filterwarnings#

You can use the @pytask.mark.filterwarnings to add warning filters to specific test items, allowing you to have finer control of which warnings should be captured at test, class or even module level:

from pathlib import Path

import pandas as pd
import pytask
from pytask import Product
from typing_extensions import Annotated


def _create_df() -> pd.DataFrame:
    df = pd.DataFrame({"a": range(10), "b": range(10, 20)})
    df[df["a"] < 5]["b"] = 1
    return df


@pytask.mark.filterwarnings("ignore:.*:SettingWithCopyWarning")
def task_warning(path: Annotated[Path, Product] = Path("df.pkl")) -> None:
    df = _create_df()
    df.to_pickle(path)

Filters applied using a mark take precedence over filters passed on the command line or configured by the filterwarnings configuration option.

Disabling warnings summary#

Although not recommended, you can use the --disable-warnings command-line option to suppress the warning summary entirely from the test run output.

Debugging warnings#

Sometimes it is not clear which line of code triggered a warning. To find the location, you can turn warnings into exceptions and then use the pytask build --pdb flag to enter the debugger.

You can use the configuration to convert warnings to errors by setting

[tool.pytask.ini_options]
filterwarnings = ["error:.*"]

and then run pytask.

Or, you use a temporary environment variable. Here is an example for bash

$ PYTHONWARNINGS=error pytask --pdb

and here for Powershell

$ $env:PYTHONWARNINGS = 'error'
$ pytask
$ Remove-Item env:\PYTHONWARNINGS