How to display errors to the user while still logging it? - python

I'm using a PyQt4 user interface. I've redirected stderr to a log file for easy debugging and trouble-shooting, but now I need to display error messages to the user when an error occurs.
My issue is that I need to catch an exception when it happens and let the user know that it happened, but still let the traceback propagate to stderr (i.e. the log file).
If I do something like this:
def updateResults(self):
try:
#code that updates the results
except:
#display error message box
This will catch the exception and not propogate to the error log.
Is there some way to show the user the message and then continue to propogate the error?
Would this work?
except, e:
#display error message box
raise e
Is there a better way to accomplish my goal?

I think you are thinking about this in the wrong way. You shouldn't be re-raising the error simply to log it further down the line. The cannonical way of doing this in Python is to use the logging module. Adapted from the docs:
import logging
LOG_FILENAME = '/tmp/logging_example.out'
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,)
...
try:
# code
except:
logging.debug('Something bad happened', exc_info=True)
# display message box
# raise (if necessary)
This gives a far more flexible logging system than relying on errors produced on sys.stdout. You may not need to re-raise the exception if you can recover from the exception in some way.

Exactly, but you can just
raise
which will re-raise the currently handled exception.

Some additional information:
(With PyQt4) you will also need to rebind sys.excepthook to your own function to catch all uncaught exceptions. Otherwise PyQt will just print them to the console, which may not be what you need...
import sys
def excepthook(exc_type, exc_val, tracebackobj):
# do something useful with the uncaught exception
...
def main():
# rebind excepthook
sys.excepthook = excepthook
...

Related

How to make python not close it self after error, python exception

I have made an program in python that i converted into .exe using auto-py-to-exe and im wondering how to stop .exe stop closing it self after an error (python exception) the .exe closes it self in the speed of light and you cant read the error.
Does someone knows how to make it not close it self?
using input doesnt work if the exception happens in a pip library
Thanks
You can use a try-except based system (that you have to build suitably to catch every exception of your code) and to print the exception you can use the module traceback like so:
try:
## code with error ##
except Exception:
print("Exception in user code:")
print("-"*60)
traceback.print_exc(file=sys.stdout)
print("-"*60)
or you could use a simpler form like:
try:
## code with error ##
except Exception as e:
print(e, file='crash log.txt')
that only prints the error class (like file not found).
I should also point out that the finally keyword exists with the purpose of executing code either if an exception arose or not:
try:
## code with error ##
except: #optional
## code to execute in case of exception ##
finally:
## code executed either way ##
Something you could do on top of that is logging everything your program does with
print(status_of_program, file=open('log.txt','a'))
this is useful to see exactly at what point the program has crashed and in general to see the program in action step by step.
But a thing you should do is properly test the program while in .py form and if it works you could possibly assume the error comes from the actual exportation method and consult the documentation or try exporting simpler programs to catch the difference (and so the error).
i'd suggest to consult:
https://docs.python.org/3/library/exceptions.html
to learn the error types and the try-except construct.
If input() doesn't work try using sys.stdout().
I gather that this is a console app. If it's a GUI app, you can use a similar approach but the details will be different.
The approach I'd use is to set sys.excepthook to be your own function that prints the exception, then waits for input. You can call the existing exception hook to actually do the printing.
import sys, traceback as tb
oldhook = sys.excepthook
def waitexcepthook(type, exception, traceback):
oldhook(type, exception, traceback)
input()
sys.excepthook = waitexcepthook

Python logger exception to file

I use logging. The logger writes to file only. (and not to standard output.) In some cases logger raises exception from inside a logger method.
My goal is say to logger not to write anything on to standard out/err, in case of any error at all. All internal exception should be handled internally, and should be written into the log file.
Details:
My logger raised charmap error. This particular issue has been solved based on this thread.
But I afraid of that in a specific case, other exception can occur (file IO error, etc), on the field, which is very frustrating, that the logger fails, while the system works. I want to ensure that the logger don't print anything on standard out/err at all.
My expected behavior is something like this:
try:
logger.debug('Some error maker')
except:
try:
logger.debug('Error during log')
except:
pass
Just, of course, I don't want to write try-except around all of my logger statement.
Is there anything similar feature in the logger? Something quiet mode?
What about a function like this?
def my_logger(thing_to_log):
try:
logger.debug(thing_to_log)
except Exception:
try:
logger.debug('Error during log')
except Exception:
pass
In the rest of the code you'll only need:
my_logger(thing_to_log)
To improve over #mdgm answer you can use the built-in features of logging to log stack trace and details of the exception:
def my_logger(thing_to_log):
try:
logger.debug(thing_to_log)
except Exception:
try:
logger.debug('Error during log', exc_info=True, stack_info=True)
except Exception:
pass

Exceptions: logging the traceback only once

I am scratching my head about what is the best-practice to get the traceback in the logfile only once. Please note that in general I know how to get the traceback into the log.
Let's assume I have a big program consisting of various modules and functions that are imported, so that it can have quite some depth and the logger is set up properly.
Whenever an exception may occur I do the following:
try:
do_something()
except MyError as err:
log.error("The error MyError occurred", exc_info=err)
raise
Note that the traceback is written to the log via the option exc_info=err.
My Problem is now that when everything gets a bit more complex and nested I loose control about how often this traceback is written to the log and it gets quite messy.
An example of the situation with my current solution for this problem is as follows:
from other_module import other_f
def main():
try:
# do something
val = other_f()
except (AlreadyLoggedError1, AlreadyLoggedError2, AlreadyLoggedError3):
# The error was caught within other_f() or deeper and
# already logged with traceback info where it occurred
# After logging it was raised like in the above example
# I do not want to log it again, so it is just raised
raise
except BroaderException as err:
# I cannot expect to have thought of all exceptions
# So in case something unexpected happened
# I want to have the traceback logged here
# since the error is not logged yet
log.error("An unecpected error occured", exc_info=err)
raise
The problem with this solution is, that I need to to keep track of all Exceptions that are already logged by myself and the line except (AlreadyLoggedError1, AlreadyLoggedError2, ...) gets arbitrary long and has to be put at any level between main() and the position the error actually occured.
So my question is: Is there some better (pythonic) way handling this? To be more specific: I want to raise the information that the exception was already logged together with the exception so that I do not have to account for that via an extra except block like in my above example.
The solution normally used for larger applications is for the low-level code to not actually do error handling itself if it's just going to be logged, but to put exception logging/handling at the highest level in the code possible, since exceptions will bubble up as far as needed. For example, libraries that send errors to a service like New Relic and Sentry don't need you to instrument each small part of your code that might throw an error, they are set up to just catch any exception and send it to a remote service for aggregation and tracking.

python logging in django

I am using the basic python logger in django and it seems to be workng well. I have the logging setup in my setting.py as;
logging.baseConfig(level = logging.NOTSET,
format='a format',
datemt=' a datefmt',
filename='path to log',
filemode = 'a')
logging.getLogger('').setLevel(logging.NOTSET)
My question is with regard to propagating exceptions. In my code if I have a try/except clause and catch the exception so I can log it, what is the best way to then propagate that error so that I can redirect to my 500 page. I have been using
try:
do stuff
except Exception, e:
logging.error(e)
raise
but I find that this causes the exeption to be logged twice. Is there another way to do this or am I doing something wrong?
Regards
Andrew
There's no need to catch the exception just so you can log it. You can log it and handle it, or else let it bubble up to some higher level which will log it and handle it. If you want to log exceptions which occur in some view, which you don't want to handle, then you can install some exception middleware which logs the exception and either returns a custom response which you determine, or None (to return whatever response Django would normally return).
There's an example of extensible exception middleware here, which doesn't actually use logging but whose log_exception() method you could subclass to log the exception, or just use that snippet as a guide to provide your own exception middleware - it's basically just a class with a method called process_exception:
class MyExceptionMiddleware:
def process_exception(self, request, exception):
#Do your logging here
Also, note that loggers have an exception() method which works like error() but includes traceback information in the log.
There's a recipe: http://code.activestate.com/recipes/466332/
In any somewhat complex application, you likely want to log and handle most exceptions. The recipe shows a way to separate logging from handling, so that it is not necessary to explicitly invoke the logging mechanism in each try-except clause.

How do I stop a program when an exception is raised in Python?

I need to stop my program when an exception is raised in Python.
How do I implement this?
import sys
try:
print("stuff")
except:
sys.exit(1) # exiting with a non zero value is better for returning from an error
You can stop catching the exception, or - if you need to catch it (to do some custom handling), you can re-raise:
try:
doSomeEvilThing()
except Exception, e:
handleException(e)
raise
Note that typing raise without passing an exception object causes the original traceback to be preserved. Typically it is much better than raise e.
Of course - you can also explicitly call
import sys
sys.exit(exitCodeYouFindAppropriate)
This causes SystemExit exception to be raised, and (unless you catch it somewhere) terminates your application with specified exit code.
If you don't handle an exception, it will propagate up the call stack up to the interpreter, which will then display a traceback and exit. IOW : you don't have to do anything to make your script exit when an exception happens.
import sys
try:
import feedparser
except:
print "Error: Cannot import feedparser.\n"
sys.exit(1)
Here we're exiting with a status code of 1. It is usually also helpful to output an error message, write to a log, and clean up.
As far as I know, if an exception is not caught by your script, it will be interrupted.

Categories