55

I'm issuing lots of warnings in a validator, and I'd like to suppress everything in stdout except the message that is supplied to warnings.warn().

I.e., now I see this:

./file.py:123: UserWarning: My looong warning message
some Python code

I'd like to see this:

My looong warning message

Edit 2: Overriding warnings.showwarning() turned out to work:

def _warning(
    message,
    category = UserWarning,
    filename = '',
    lineno = -1):
    print(message)
...
warnings.showwarning = _warning
warnings.warn('foo')
Tim Stack
  • 3,209
  • 3
  • 18
  • 39
l0b0
  • 55,365
  • 30
  • 138
  • 223

4 Answers4

46

There is always monkeypatching:

import warnings

def custom_formatwarning(msg, *args, **kwargs):
    # ignore everything except the message
    return str(msg) + '\n'

warnings.formatwarning = custom_formatwarning
warnings.warn("achtung")
Asclepius
  • 57,944
  • 17
  • 167
  • 143
Otto Allmendinger
  • 27,448
  • 7
  • 68
  • 79
  • on Python 3.6 I get TypeError: custom_formatwarning() got an unexpected keyword argument 'line'. So I changed function signature to: `def custom_formatwarning(message, category, filename, lineno, line='')` – Noam Manos Sep 04 '17 at 06:54
  • I had the "same got an unexpected keyword argument 'line'" in Python 3.6, but I just changed the signature to `def custom_formatwarning(msg, *a, **b):` so it also catches keyword args. – SuperGeo Jan 25 '18 at 18:44
  • 13
    I know this thread is old, but, you can also do this with a lambda instead of a function: `warnings.formatwarning = lambda msg, *args, **kwargs: f'{msg}\n'` – Craig Nov 06 '18 at 16:13
  • this should be the accepted answer, not the other one – DataMan Sep 10 '20 at 01:08
  • How do I get the warning type like `DeprecationWarning`? I tried `category` but it contains nothing – reddy Mar 01 '21 at 10:24
  • This works, although I found `mypy` complained about it. If I'm reading the Python docs correctly, we should instead override `showwarning()`. Doing this and using the explicit signature made `mypy` happy. https://docs.python.org/3/library/warnings.html#warnings.showwarning – Lorem Ipsum Oct 04 '22 at 02:54
20

Monkeypatch warnings.showwarning() with your own custom function.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
13

Use the logging module instead of warnings.

Geoff Reedy
  • 34,891
  • 3
  • 56
  • 79
  • 2
    This is what I have ended up with in the vast majority of situations where I originally tried to use `warnings`. If you are struggling with `warnings`, you should consider this option. Seriously. – tripleee Apr 08 '17 at 07:48
  • 1
    there's some subtlety in choosing warnings over logging.warn https://stackoverflow.com/a/14762106/5335565 – Izana Jun 09 '20 at 22:33
11

Here's what I'm doing to omit just the source code line. This is by and large as suggested by the documentation, but it was a bit of a struggle to figure out what exactly to change. (In particular, I tried in various ways to keep the source line out of showwarnings but couldn't get it to work the way I wanted.)

# Force warnings.warn() to omit the source code line in the message
formatwarning_orig = warnings.formatwarning
warnings.formatwarning = lambda message, category, filename, lineno, line=None: \
    formatwarning_orig(message, category, filename, lineno, line='')

Just passing line=None would cause Python to use filename and lineno to figure out a value for line automagically, but passing an empty string instead fixes that.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • I know this is super old but I've done a similar thing and that also worked. However if I do this inside a function, the warning behavior changes on the global scope. Every warning comes after calling that function adopts the modified behavior. Do you know a way to limit its effect? – percusse Oct 05 '17 at 13:14
  • Hmm, I only ever used this in global context. As a freak workaround, you could define a global variable which is used inside the `lambda` to decide whether or not the `line` value is overridden or not. (At that point, maybe use a named function rather than a `lambda`?) – tripleee Oct 05 '17 at 15:22
  • Unfortunately it didn't matter where I did these things. I also tried the original defeinition saving and restoring but no avail yet. – percusse Oct 05 '17 at 15:36
  • Nevermind this is a known issue apparently https://bugs.python.org/issue18081#msg191342. It is indeed annoying – percusse Oct 06 '17 at 14:47