I want to catch and then re-throw warnings from my Python code, similarly to try/except clause. My purpose is to catch the warning and then re-throw it using my logger.
The warnings are issued from whatever packages I'm using, I would like something that is totally generic, exactly like the try/except clause.
How can I do that in Python >= v3.8?
There are at least two ways to tackle this:
You could use warnings.catch_warnings with record=True to record the Warning objects. This way all your application code will get executed regardless of any warnings.
import warnings
import logging
logger = logging.getLogger(__name__)
class NotImportantWarning(UserWarning):
...
def do_something():
warnings.warn("doing something", UserWarning)
warnings.warn("This is not important", NotImportantWarning)
# Executing our main function and recording warnings
with warnings.catch_warnings(record=True) as recorded_warnings:
do_something()
print("done")
# Handling warnings. You may log it here.
for w in recorded_warnings:
if isinstance(w.message, NotImportantWarning):
continue
# re-issue warning
warnings.warn_explicit(
message=w.message,
category=w.category,
filename=w.filename,
lineno=w.lineno,
source=w.source,
)
# or use a logger
logger.warning(str(w.message))
This will print then something like
done
<ipython-input-6-cc898056d044>:12: UserWarning: doing something
warnings.warn("doing something", UserWarning)
doing something
warnings.warn is that with the warn_explicit it is possible to retain the original filename and line number information.If you really want to break the control flow right at the warning, like with exceptions, it is possible with warnings.filterwarnings("error"):
import warnings
warnings.filterwarnings('error')
try:
do_something()
except UserWarning as w:
print(w)
Note: The code execution stops at the first warning. No code inside do_something after that warning will ever get executed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With