'How to properly raise errors and log them when comparing variables or validating formats with custom if statements?
In a module I am writing, I have a need for checking that incomming data matches particular requirements and formats. I thought I knew a good way to do this, but I need to add logging functionality and it made me realise I must be writing my code improperly. A MWE of what I am currently doing is:
string1 = 'Hello, World!' # represents something like a column name in an incoming dataframe
string2 = 'Hello, World?' # represents what the column name should be according to an incomming config file
if string1 != string2:
raise ValueError('Input from string1 does not match expected value given in string2')
That works perfectly, and the raised error can be grabbed by my pytest functions as well. But it is not part of a try except sequence, and I dont see how it can be. try doesn't behave like an if and except requires the specific error to actually be raised first.
This poses a problem because I dont know how to capture the raised error with python's logging module without needless code duplication. The best I can do is:
import logging
string1 = 'Hello, World!' # represents something like a column name in an incoming dataframe
string2 = 'Hello, World?' # represents what the column name should be according to an incomming config file
if string1 != string2:
logging.error('Input from string1 does not match expected value given in string2')
raise ValueError('Input from string1 does not match expected value given in string2')
But that is two, nearly identical lines to do the same thing. logging.error doesnt actually halt the code, which I need to happen, and I cant find a way to capture the raise ValueError(...) with logging.
Obviously, with this example, logging is just going to print to the terminal, but ultimately, it will be printing to a file (and I know how to do that).
What is the best way to write such a test of variables to have both logging and raised error functionality?
Solution 1:[1]
The idea is to put the raise in a try block and do the logging in the except. Here's how you'd do it for this small example:
string1 = 'Hello, World!'
string2 = 'Hello, World?'
try:
if string1 != string2:
raise ValueError('Input from string1 does not match expected value given in string2')
except ValueError as e:
logging.error(e)
raise
In real life, it tends to look more like:
try:
do_some_complex_thing()
except Exception as e:
log.error(e)
where do_some_complex_thing() might have a lot going on inside of it -- by wrapping it all in one outer try block you can make sure that any otherwise-unhandled exception is logged in a single spot.
Solution 2:[2]
I'm not very familiar with the logging module but this might help:
Exceptions in python are just objects, and you can generate them without raising them immediately.
err = ValueError('Input from string1 does not match expected value given in string2')
# log the error like you would in an except block and then
raise err
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Joe |
