Issue
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?
Solution
There are at least two ways to tackle this:
- Record the warnings and replay them
- Make warnings to behave like exceptions and break the control flow
Option 1: Record warnings and replay them
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
Notes
- Using the lower level warnings.warn_explicit to re-issue the warnings. The denefit over
warnings.warn
is that with thewarn_explicit
it is possible to retain the original filename and line number information.
Option 2: Make warnings to behave like exceptions
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.
Answered By - Niko Fohr
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.