Is it possible to add a Custom Message globally on runtime-erros? I would like to have a time-stamp as this would help figuring out if a file eventually was written by that execution process.
Replacing sys.excepthook with an appropriate function will allow you to do whatever you like upon every occurrence of an uncaught exception.
Take a look at the Python docs (2, 3) on handling exceptions. You can catch the RuntimeError and print the original message along with a custom timestamp. For more information on accessing the stack trace and exception messages, check out this question.
Ignacio's solution is also great if you'd like to set the message globally.
Related
I created a big program that does a lot of different stuff. In this program, I added some error management but I would like to add management for critical errors which should start the critical_error_function().
So basically, I've used :
try :
//some fabulous code
except :
critical error(error_type)
But I am here to ask if a better way to do this...
In Python exceptions are the intended way of error handling. Assuming you wrap your whole program in one try-except block, a better way would be to
only try-except-wrap the lines that can generate exceptions instead of your complete program
catch them with a specific exception such as ValueError or even your own custom exception instead of the blank except statement
handle them appropriately. Handling could mean skipping this value, logging the error or calling your critical_error_function.
Is this idiomatic/pythonic to do like this or is there a better way? I want all the errors to get in log for in case I don't have access to the console output. Also I want to abort this code path in case the problem arises.
try:
with open(self._file_path, "wb") as out_f:
out_f.write(...)
...
except OSError as e:
log("Saving %s failed: %s" % (self._file_path, str(e)))
raise
EDIT: this question is about handling exceptions in a correct place/with correct idiom. It is not about logging class.
A proven, working scheme is to have a generic except clause at the top level of your application code to make sure any unhandled error will be logged (and re-raised fo course) - and it also gives you an opportunity to try and do some cleanup before crashing)
Once you have this, adding specific "log and re-reraise" exception handlers in your code makes sense if and when you want to capture more contextual informations in your log message, as in your snippet example. This means the exception might end up logged twice but this is hardly and issue .
If you really want to be pythonic (or if you value your error logs), use the stdlib's logging module and it's logger.exception() method that will automagically add the full traceback to the log.
Some (other) benefits of the logging module are the ability to decouple the logging configuration (which should be handled by the app itself, and can be quite fine-grained) from the logging calls (which most often happen at library code level), the compatibility with well-written libs (which already use logging so you just have to configure your loggers to get infos from 3rd-part libs - and this can really save your ass), and the ability to use different logging mechanisms (to stderr, to file, to syslog, via email alerts, whatever, and you're not restricted to a single handler) according to the log source and severity and the deployment environment.
Update:
What would you say about re-raising the same exception (as in example) or re-raising custom exception (MyLibException) instead of original one?
This is a common pattern indeed, but beware of overdoing it - you only want to do this for exceptions that are actually expected and where you really know the cause. Some exception classes can have different causes - cf OSError, 'IOErrorandRuntimeError- so never assume anything about what really caused the exception, either check it with a decently robust condition (for example the.errnofield forIOError`) or let the exception propagate. I once wasted a couple hours trying to understand why some lib complained about a malformed input file when the real reason was a permission issue (which I found out tracing the library code...).
Another possible issue with this pattern is that (in Python2 at least) you will loose the original exception and traceback, so better to log them appropriately before raising your own exception. IIRC Python3 has some mechanism to handle this situation in a cleaner way that let you preserve some of the original exception infos.
There is a function called record_exception() that you can use if you want to send an error to newrelic.
The question is how to record an error when you don't have an exception in hand? I just want to decide somewhere in the code to record an event to newrelic.
To record generic events that are not errors, you can create a custom metric and then use record_custom_metric, like this:
newrelic.agent.record_custom_metric('Custom/MyValue', 42)
Please see the naming reference to make sure you are naming the metric correctly.
What's the point of using raise if it exits the program?
Wouldn't it be just as effective to allow the crash to happen?
If I leave out the try-except block, the function crashes when I divide by zero and displays the reason. Or is there some other use that I don't know about?
def div(x,y):
try:
return(x/y)
except ZeroDivisionError as problem:
raise (problem)
I your case effect would be the same. But you may want to perform some additional logic in case of error (cleanup etc.) and perhaps raise a different (perhaps custom) error instead of original system low-level one, like with a message "Incorrect data, please check your input". And this can be done catching the error and raising a different one.
There is no point (in this case) in using raise. Normally, you'd have some code in there to do "something else" - that could include outputting some more debug information, writing some log data out, retrying the operation with a different set of parameters, etc. etc. etc.
I'm not sure there's much value in your case, where when an exception occurs it just re-raises it - it seems like someone (perhaps) intended to write some sort of handling code there, but just never got around to it.
Some great examples of the use cases for exception handling are in the Python Exception Handling Wiki --> http://wiki.python.org/moin/HandlingExceptions
The reason to re-raise an exception is to allow whatever code is calling you the opportunity to handle it after you have done something to handle it yourself. For example, you have closed a file that you were using (because cleanliness is a virtue) but your code cannot continue.
If you are not going to do anything to handle the exception, then no, there is no reason to write an exception handler for it!
The correct way to re-raise an exception is to simply use raise without any arguments. This way, whoever catches the exception (or the user of the script, if nobody catches it) gets a correct stack trace that tells where the exception was originally raised.
I'm thinking about where to write the log record around an operation. Here are two different styles. The first one, write log before the operation.
Before:
log.info("Perform operation XXX")
operation()
And here is a different style, write the log after the operation.
After:
operation()
log.info("Operation XXX is done.")
With the before-style, the logging records say what is going to do now. The pro of this style is that when something goes wrong, developer can detect it easily, because they know what is the program doing now. But the con is that you are not sure is the operation finished correctly, if something wrong is inside the operation, for example, a function call gets blocked there and never return, you can't never know it by reading the logging records. With the after-style, you are sure the operation is done.
Of course, we can mix those two style together
Both:
log.info("Perform operation XXX")
operation()
log.info("Operation XXX is done.")
But I feel that is kinda verbose, it makes double logging records. So, here is my question - what is the good logging style? I would like to know how do you think.
I'd typically use two different log levels.
The first one I put on a "debug" level, and the second one on an "info" level. That way typical production machines would only log what's being done, but I can turn on the debug logging and see what it tries to do before it errors out.
It all depends what you want to log. If you're interested in the code getting to the point where it's about to do an operation. If you want to make sure the operation succeeded, do it after. If you want both, do both.
Maybe you could use something like a try catch ? Here 's a naive python example :
try :
operation()
log.info("Operation XXX is done.")
except Exception:
log.info("Operation xxx Failed")
raise Exception() # optional : if you want to propagate failure to another try catch statement and/or crash eventually.
Operation will be launched.
If it doesn't fail (no exception raised) you get a success statement in the logs.
If it fails (by raising an exception. Like disc full or whatever you are trying to do), Exception is caught and you get a failure statement.
Log is more meaning full. You get to keep the verbosity to a oneliner and get to know if operation succeeded. Best of all choices.
Oh and you get a hook point where you can add some code to be executed in case of failure.
I hope it help.
There's another style that I've seen used in Linux boot scripts and in strace. It's got the advantages of your combined style with less verbosity, but you've got to make sure that your logging facility isn't doing any buffering. I don't know log.info, so here's a rough example with print:
print "Doing XXX... ", # Note lack of newline :)
operation()
print "Done."
(Since in most cases print uses buffering, using this example verbatim won't work properly. You won't see "Doing XXX" until you see the "Done". But you get the general idea.)
The other disadvantage of this style is that things can get mixed up if you have multiple threads writing to the same log.