Catching an exception in clone_saved_path() - python

I'm trying to figure out how to get the exception to show for this function
clone_saved_path():
def clone_saved_path():
except OSError as e:
# If the error was caused because the source wasn't a directory
print('Directory not copied. Error: %s' % e)
print("got here. [4]")
except:
print("Another error occurred in clone_saved_path() ")
print("got here. [5]")
When I run my code, it hits the last except block and outputs:
print("Another error occurred in clone_saved_path() ")
I know this may sound basic, but I need to figure out how to show the actual exception.

https://docs.python.org/3/library/sys.html#sys.exc_info
"This function returns a tuple of three values that give information about the exception that is currently being handled."
So you could do something like the below (suggested here: https://docs.python.org/3/tutorial/errors.html#handling-exceptions):
import sys
# ...
except:
print("Another error occurred in clone_saved_path() ")
print(sys.exc_info()[0]) # type of exception
raise

Related

How to continue with the execution even if i catch an error [duplicate]

This question already has answers here:
Catch exception and continue try block in Python
(12 answers)
Closed 11 months ago.
I want to control the error just printing it but continuing with the rest, por example:
try:
list =('a',2,3,5,6,'b',8)
print(list[8])
print("continue execution")
except:
print("An exception occurred")
It just will print the error but not the continue execution, is possible to continue even after exception?
What is missing and you're looking for is the finally instruction.
Syntax:
try:
#search for errors
except:
#if errors found, run this code
finally:
#run this code no matter if errors found or not, after the except block
The finally block contains the code that will be run after the except block, no matter if errors were raised or not.
See if this rearrangement of your own code helps:
list =('a',2,3,5,6,'b',8)
try:
print(list[8])
except:
print("An exception occurred")
print("continue execution")
If it matters for you to "print continue" right after exception occurrence , then you can put whatever you want to do before exception in a "bool function" and then inside the "try" check if function succeed or not.it means "if error occurred continue ,else show "An exception occurred".
try:
assert doStuff() == False
print("continue execution")
except:
print("An exception occurred")

How to raise additional error in Python and keep cause in stack trace?

I wrote
try:
...
except Exception as e:
raise ValueError(e, "Was unable to extract date from filename '%s'" % filename)
and now, when exception occurs inside try block, I loose information about it. I stack trace printed I see only line number with raise statement and no infomation about where actual e occured.
How to fix?
Use raise exc from another_exc:
try:
...
except Exception as e:
raise ValueError("Was unable to extract date from filename '%s'" % filename) from e
Adding the from e will make sure there's two tracebacks connected by The above exception was the direct cause of the following exception".

How many exceptions are possible when reading a json in Python/django?

I have:
MY_PATH_DIR = 'path/to/my/json/file.json'
try:
with open(MY_PATH_DIR, 'r') as f:
MY_PATH_DIR = json.load(f)
except IOError, RuntimeError, ValueError:
pass
except PermissionDenied:
pass
And I want to catch all possible errors. With
IOError - I am catching errors when the file doesn't exist or has a
syntax error (non valid JSON).
RuntimeError - couldn't test it but I think that makes sense from the
documentation in case of an unexpected error
ValueError - I got from here in case nothing got returned
PermissionDenied - is a specific Django error
Are there any other Exceptions that would make sense? I'm not sure if OSError makes sense here. I think that would be raised earlier, right?
The purpose of capturing exceptions is to control the program's behavior when something bad happened, but in an expected way. If you are not even sure what would cause that exception happen, capturing it would only swallow the underlying programming errors you might have.
I wouldn't add as many kinds of exception as possible to that single block of code, you should only add what you care about. To take it to extreme, each line of code would yield certain exceptions but for obvious reason you couldn't do try except for all of them.
Edit:
For the sake of correctness, since you mentioned I don't want my code to break in any case, you could simply do:
try:
# json.load
except Exception as e:
print "Let's just ignore all exceptions, like this one: %s" % str(e)
This is would give you what exception happens as output.
import random
import sys
def main():
"""Demonstrate the handling of various kinds of exceptions."""
# This is like what you are doing in your code.
exceptions = IOError, RuntimeError, ValueError
try:
raise random.choice(exceptions)()
except exceptions as error:
print('Currently handling:', repr(error))
# The following is not much different from Shang Wang's answer.
try:
raise random.choice(exceptions)()
except Exception as error:
print('Currently handling:', repr(error))
# However, the following code will sometimes not handle the exception.
exceptions += SystemExit, KeyboardInterrupt, GeneratorExit
try:
raise random.choice(exceptions)()
except Exception as error:
print('Currently handling:', repr(error))
# The code can be slightly altered to take the new errors into account.
try:
raise random.choice(exceptions)()
except BaseException as error:
print('Currently handling:', repr(error))
# This does not take into account classes not in the exception hierarchy.
class Death:
pass
try:
raise Death()
except BaseException as error:
print('Currently handling:', repr(error))
# If your version of Python does not consider raising an exception from an
# instance of a class not derived from the BaseException class, the way to
# get around this problem would be with the following code instead.
try:
raise Death()
except:
error = sys.exc_info()[1]
print('Currently handling:', repr(error))
if __name__ == '__main__':
main()

Library File for exception handling in python

I have written a script in python which has except handling(catch block) for all the runtime exceptions.If i m putting the try block inside the same file as script then its printing the exception but my need is if the try block is in a different file then whats the procedure that it will use the catch blocks written in the script.
import traceback
import sys
import linecache
try:
# execfile(rahul2.py)
def first():
second()
def second():
i=1/0;
def main():
first()
if __name__ == "__main__":
main()
except SyntaxError as e:
exc_type, exc_value, exc_traceback = sys.exc_info()
filename = exc_traceback.tb_frame.f_code.co_filename
lineno = exc_traceback.tb_lineno
line = linecache.getline(filename, lineno)
print("exception occurred at %s:%d: %s" % (filename, lineno, line))
print("**************************************************** ERROR ************************************************************************")
print("You have encountered an error !! no worries ,lets try figuring it out together")
print(" It looks like there is a syntax error in the statement:" , formatted_lines[2], " at line number " , exc_traceback.tb_lineno)
print("Make sure you look up the syntax , this may happen because ")
print(" Remember this is the error message always thrown " "'" ,e , "'")
Similarly i have written for other exceptions...
Now my question is suppose i want to use this script for all the programs or like suppose the try block in in a different file ...then how i can link my script and the program which has try block..
or if i put it in different words then what i want is whenever there is an try catch block then the catch block should executed as per my script instead of the built in library..
If you want to handle this exception in a script that calls this one you need to raise up the exception. For example:
except SyntaxError as e:
exc_type, exc_value, exc_traceback = sys.exc_info()
filename = exc_traceback.tb_frame.f_code.co_filename
lineno = exc_traceback.tb_lineno
line = linecache.getline(filename, lineno)
print("exception occurred at %s:%d: %s" % (filename, lineno, line))
print("**************************************************** ERROR ************************************************************************")
print("You have encountered an error !! no worries ,lets try figuring it out together")
print(" It looks like there is a syntax error in the statement:" , formatted_lines[2], " at line number " , exc_traceback.tb_lineno)
print("Make sure you look up the syntax , this may happen because ")
print(" Remember this is the error message always thrown " "'" ,e , "'")
#### Raise up the exception for handling in a calling script ####
raise e
Then in your calling script you just put another try-except block (assuming the 'library file' you wrote is called mymodule.py and both files reside in the same working directory) like so
try:
import mymodule
mymodule.main()
except SyntaxError as e:
print("Exception found") # Optional: Add code to handle the exception
Keep in mind that if you fail to handle this re-raised exception it will cause your script to fail and exit (printing the exception message and stack trace). This is a good thing. A script which encounters a fatal error should fail in a way that gets the attention to the user if the method of recovery is unknown or cannot be handled programmatically.

python exception message capturing

import ftplib
import urllib2
import os
import logging
logger = logging.getLogger('ftpuploader')
hdlr = logging.FileHandler('ftplog.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.INFO)
FTPADDR = "some ftp address"
def upload_to_ftp(con, filepath):
try:
f = open(filepath,'rb') # file to send
con.storbinary('STOR '+ filepath, f) # Send the file
f.close() # Close file and FTP
logger.info('File successfully uploaded to '+ FTPADDR)
except, e:
logger.error('Failed to upload to ftp: '+ str(e))
This doesn't seem to work, I get syntax error, what is the proper way of doing this for logging all kind of exceptions to a file
You have to define which type of exception you want to catch. So write except Exception, e: instead of except, e: for a general exception (that will be logged anyway).
Other possibility is to write your whole try/except code this way:
try:
with open(filepath,'rb') as f:
con.storbinary('STOR '+ filepath, f)
logger.info('File successfully uploaded to '+ FTPADDR)
except Exception, e: # work on python 2.x
logger.error('Failed to upload to ftp: '+ str(e))
in Python 3.x and modern versions of Python 2.x use except Exception as e instead of except Exception, e:
try:
with open(filepath,'rb') as f:
con.storbinary('STOR '+ filepath, f)
logger.info('File successfully uploaded to '+ FTPADDR)
except Exception as e: # work on python 3.x
logger.error('Failed to upload to ftp: '+ str(e))
The syntax is no longer supported in python 3. Use the following instead.
try:
do_something()
except BaseException as e:
logger.error('Failed to do something: ' + str(e))
If you want the error class, error message, and stack trace, use sys.exc_info().
Minimal working code with some formatting:
import sys
import traceback
try:
ans = 1/0
except BaseException as ex:
# Get current system exception
ex_type, ex_value, ex_traceback = sys.exc_info()
# Extract unformatter stack traces as tuples
trace_back = traceback.extract_tb(ex_traceback)
# Format stacktrace
stack_trace = list()
for trace in trace_back:
stack_trace.append("File : %s , Line : %d, Func.Name : %s, Message : %s" % (trace[0], trace[1], trace[2], trace[3]))
print("Exception type : %s " % ex_type.__name__)
print("Exception message : %s" %ex_value)
print("Stack trace : %s" %stack_trace)
Which gives the following output:
Exception type : ZeroDivisionError
Exception message : division by zero
Stack trace : ['File : .\\test.py , Line : 5, Func.Name : <module>, Message : ans = 1/0']
The function sys.exc_info() gives you details about the most recent exception. It returns a tuple of (type, value, traceback).
traceback is an instance of traceback object. You can format the trace with the methods provided. More can be found in the traceback documentation .
There are some cases where you can use the e.message or e.messages.. But it does not work in all cases. Anyway the more safe is to use the str(e)
try:
...
except Exception as e:
print(e.message)
Updating this to something simpler for logger (works for both python 2 and 3). You do not need traceback module.
import logging
logger = logging.Logger('catch_all')
def catchEverythingInLog():
try:
... do something ...
except Exception as e:
logger.error(e, exc_info=True)
... exception handling ...
This is now the old way (though still works):
import sys, traceback
def catchEverything():
try:
... some operation(s) ...
except:
exc_type, exc_value, exc_traceback = sys.exc_info()
... exception handling ...
exc_value is the error message.
You can use logger.exception("msg") for logging exception with traceback:
try:
#your code
except Exception as e:
logger.exception('Failed: ' + str(e))
Using str(e) or repr(e) to represent the exception, you won't get the actual stack trace, so it is not helpful to find where the exception is.
After reading other answers and the logging package doc, the following two ways works great to print the actual stack trace for easier debugging:
use logger.debug() with parameter exc_info
try:
# my code
except SomeError as e:
logger.debug(e, exc_info=True)
use logger.exception()
or we can directly use logger.exception() to print the exception.
try:
# my code
except SomeError as e:
logger.exception(e)
After python 3.6, you can use formatted string literal. It's neat! (https://docs.python.org/3/whatsnew/3.6.html#whatsnew36-pep498)
try
...
except Exception as e:
logger.error(f"Failed to upload to ftp: {e}")
You can try specifying the BaseException type explicitly. However, this will only catch derivatives of BaseException. While this includes all implementation-provided exceptions, it is also possibly to raise arbitrary old-style classes.
try:
do_something()
except BaseException, e:
logger.error('Failed to do something: ' + str(e))
If you want to see the original error message, (file & line number)
import traceback
try:
print(3/0)
except Exception as e:
traceback.print_exc()
This will show you the same error message as if you didn't use try-except.
for the future strugglers,
in python 3.8.2(and maybe a few versions before that), the syntax is
except Attribute as e:
print(e)
Use str(ex) to print execption
try:
#your code
except ex:
print(str(ex))
In Python 3, str(ex) gives us the error message. You could use repr(ex) to get the full text, including the name of the exception raised.
arr = ["a", "b", "c"]
try:
print(arr[5])
except IndexError as ex:
print(repr(ex)) # IndexError: list index out of range
print(str(ex)) # list index out of range
There is also a way to get the raw values passed to the exception class without having to change the content type.
For e.g I raise type codes with error messages in one of my frameworks.
try:
# TODO: Your exceptional code here
raise Exception((1, "Your code wants the program to exit"))
except Exception as e:
print("Exception Type:", e.args[0][0], "Message:", e.args[0][1])
Output
Exception Type: 1 Message: 'Your code wants the program to exit'
The easiest way to do this is available through the Polog library. Import it:
$ pip install polog
And use:
from polog import log, config, file_writer
config.add_handlers(file_writer('file.log'))
with log('message').suppress():
do_something()
Note how much less space the code has taken up vertically: only 2 lines.

Categories

Resources