I am trying to figure out how I would print an exception if I don't know what the exception is in the first place. How would I do the following?
try:
some_command
except:
print *full_exception_trace*
Like the tutorial says.
try:
something()
except SomeException as e:
something_else(e)
You may find traceback useful.
def exception(self)
try:
Something.objects.all()
except Exception, err:
print err.message #(if you want)
#raise err
raise # The 'raise' statement with no arguments inside an error
# handler tells Python to re-raise the exception with the
# original traceback intact
err.message will give you the reason of the exception
The traceback module's print_exc() function seems to be what you want. Docs
Related
If have a function were I request some data from a website but when I get an error I want to print the error and restart my code. But I don't know the exact code, can please someone help me? This is a code example:
import time
input1 = input("Blabla: ")
def repeat():
try:
if input1 == "123":
raise "Error: 123"
except Exception as e:
print(e)
time.sleep(5) # Wait 5 seconds
repeat() # Rerun code
repeat()
When I run this code I get the error 'exceptions must derive from BaseException'. Can someone help me?
You can't just raise random strings as an exception. If you want to raise a general exception without defining a relevant type, just raise Exception, replacing:
raise "Error: 123"
with:
raise Exception("Error: 123") # The "Error: " should probably be removed
Alternatively, if you can use a more specific error, do so. If 123 is invalid because the value is wrong, use ValueError instead of Exception. If there is some more specific reason, make a subclass to make it easier for others to catch, e.g. (at top level in the module):
class SpecialValueError(ValueError):
pass
so you can do:
raise SpecialValueError("Error: 123")
and people can catch it specifically, or via plain except ValueError:, except Exception:, etc.
Right now you are printing the error object's str while you need to print it's representation
Try this:
def repeat():
try:
if input1 == "123":
raise Exception("Error: 123") # You need to use an Exception class
except Exception as e:
print(repr(e)) # Notice I added repr()
time.sleep(5)
repeat()
Exception's Representation vs Exception's String
String:
try:
raise Exception("Exception I am!")
except Exception as e:
print(e)
# Output: Exception I am!
Representation:
try:
raise Exception("Exception I am!")
except Exception as e:
print(repr(e))
# Output: Exception('Exception I am!')
How can I ignore a certain exception to be raised to the caller in python 3?
Example:
def do_something():
try:
statement1
statement2
except Exception as e:
# ignore the exception
logging.warning("this is normal, exception is ignored")
try:
do_something()
except Exception as e:
# this is unexpected control flow, the first exception is already ignored !!
logging.error("unexpected error")
logging.error(e) # prints None
I found someone mentioned that "Because of the last thrown exception being remembered in Python, some of the objects involved in the exception-throwing statement are being kept live indefinitely" and then mentioned to use "sys.exc_clear()" in this case which is not available anymore in python 3. Any clue how can I completely ignore the exception in python3?
There's no need to do this in Python 3, sys.exc_clear() was removed because Python doesn't store the last raised exception internally as it did in Python 2:
For example, in Python 2, the exception is still kept alive when inside a function:
def foo():
try:
raise ValueError()
except ValueError as e:
print(e)
import sys; print(sys.exc_info())
Calling foo now shows the exception is kept:
foo()
(<type 'exceptions.ValueError'>, ValueError(), <traceback object at 0x7f45c57fc560>)
You need to call sys.exc_clear() in order to clear the Exception raised.
In Python 3, on the contrary:
def foo():
try:
raise ValueError()
except ValueError as e:
print(e)
import sys; print(sys.exc_info())
Calling the same function:
foo()
(None, None, None)
Using custom exceptions in python (v2.7.3): don't get a stack trace when call getSub() whereas getSub(True) invokes one, the difference being that it is caused via an additional try...except which I want to avoid (+feels unnecessary) so why/how can it be avoided?
import sys, traceback
class customException(Exception):
def __init__(self, *args):
super(customException,self).__init__(*args)
print "Stack trace within exception", traceback.extract_tb(sys.exc_info()[2])
errTxt = [a for a in args]
print "error text", errTxt
def getFn():
try:
getSub()
except customException as e:
print "customException was raised"
try:
getSub(True)
except customException as e:
print "customException2 was raised"
def getSub(flag=False):
if flag:
try:
1/0
except:
raise customException('test')
else:
raise customException('test')
getFn()
output:
Stack trace within exception []
error text ['test']
customException was raised
Stack trace within exception [('./test3.py', 25, 'getSub', '1/0')]
error text ['test']
customException2 was raised
To put the above in context I have code (pseudo) along the below lines and it wasn’t until I boiled down the code to the above example that I realised why the traceback access was not always working. The purpose of the custom exception class is to collect an aggregate count of exceptions in order to classify downstream the result of each do_something, e.g. fatal, warning etc. The use of the traceback was to record from WHERE the exception was ‘raised’ and therefore the creation of an exception (1/0 = albeit seems out of place) enables that to work. Wondering about using the inspect module rather than thinking about this within the traceback stack?
__main__
With each item in set:
Try:
do_something(item)
except customException()
clean up = log info etc.
end With
end.__main__
do_something(item)
try:
check_something()
except customException
if exception=typeA.1 raise customException(Type1)
if exception=typeB.2 and item = ‘x’
raise customException(Type2)
check_something()
a = getInfo()
unless getInfo()
raise customException(typeA.1)
try:
b = getOtherInfo()
except customException
raise customException(typeB.2)
…
If I understand you right, you're wondering why your print "Stack trace within exception" line prints an empty list for getSub(), but prints some traceback info for getSub(True).
You have code in your exception class's __init__ to look at the most recent exception via sys.exc_info. When you do raise customException('test'), customException('test') is evaluated first on its own, before it "knows" that it is going to be raised as an exception. So when you do that raise in getSub(), there is no most recent exception.
With getSub(True), there is a most recent exception, because the 1/0 raises an exception before you create your customException. Note that when you do 1/0, the most recent exception is the one from that 1/0; you can see that there's nothing about your customException in that traceback.
An exception object has to be created before the exception is raised. So you can't look at "the current exception" in your exception class's __init__ to get info about the stack trace that will be created when it is raised, because it hasn't been raised yet at that time.
If you want, you could use traceback.extract_stack to get the call stack at the time the exception object is created, but there's no guarantee that that has anything to do with when it will be raised. Just because an instance of your exception class is created doesn't even mean it will ever be raised at all. It's perfectly legal (although generally pointless) for someone to just create an exception object with stuff = customException('blah') but never actually raise the exception.
In any case, it's not clear from your question what you're trying to achieve here. It would help if you explained that.
Because you're catching the exception, there will be no traceback unless you either explicitly re-raise
try:
getSub(True)
except customException as e:
print "customException2 was raised"
raise # add this to re-raise, with original traceback
or print it yourself:
try:
getSub(True)
except customException as e:
print "customException2 was raised"
print traceback.format_exc()
my code is like below
class Something(models.Model)
def exception(self)
try:
Something.objects.all()
except Exception():
raise Exception()
called this method from testcases ,its working but i need to raise exception ,it does not catch the exception
and here is my test case
def test_exception(self):
instance = Something()
instance.exception()
its working fine but i need to raise exception from except block
This line:
except Exception():
should be:
except Exception:
def exception(self)
try:
Something.objects.all()
except Exception, err:
#print err.message (if you want)
raise err
This will catch the error and print the exact msg if required.
Why catch the Exception just to re-raise it?
If you are not doing anything in the except suite except re-raising the exception, then simply do not catch the exception in the first place:
#staticmethod
def exception():
Something.objects.all()
If you are doing something nontrivial inside the except suite, then:
def exception(self):
try:
Something.objects.all()
except Exception:
# do something (with self?)
raise
Then, to test that the exception method raises an Exception:
def test_exception(self):
instance = Something()
self.assertRaises(Exception, instance.exception)
This depends on Something.objects.all() raising Exception.
PS. If exception does not depend on self, then it is best to remove it from the argument list and make exception a staticmethod.
PPS. Exception is a very broad base exception class. A more specific exception would be more helpful for debugging, and allow other code to catch this specific exception instead of forcing it to handle any possible Exception.
I'm currently writing a wrapper class. I want to be able to log exceptions properly but allow calling methods to be aware of exceptions which occur. My class looks like this:
import logging
log = logging.getLogger('module')
class MyAPIWrapper(library.APIClass):
def __init__(self):
self.log = logging.getLogger('module.myapiwrapper')
def my_wrapper_method(self):
try:
response = self.call_api_method()
return response.someData
except APIException, e:
self.log.exception('Oh noes!')
raise e #Throw exception again so calling code knows it happened
I'm a bit dubious about catching and exception just to log it and then re-raising it so the calling code can do something about it. What's the proper pattern here?
There is nothing wrong with catching to log. However, I'd recommend:
try:
response = self.call_api_method()
except APIException, e: # or 'as e' depending on your Python version
self.log.exception('Oh noes!')
raise #Throw exception again so calling code knows it happened
else:
return response.someData
By just doing a bare raise you preserve the full traceback info. It's also more explicit to put code that will only happen if you don't have an exception in the else clause, and it's clearer what line you're catching an exception from.
It would also be fine for the calling class to do the logging if it's handling the error anyway, but that may not be convenient for your app.
Edit: The documentation for try ... except ... else ... finally is under compound statements.
That method is correct, although instead of raise e you should just use raise, which will automatically re-raise the last exception. This is also one of the rare cases where using a blanket except is considered acceptable.
Here is an example very similar to what you are doing from the Python docs on Handling Exceptions:
The last except clause may omit the exception name(s), to serve as a wildcard. Use this with extreme caution, since it is easy to mask a real programming error in this way! It can also be used to print an error message and then re-raise the exception (allowing a caller to handle the exception as well):
import sys
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as (errno, strerror):
print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
print "Could not convert data to an integer."
except:
print "Unexpected error:", sys.exc_info()[0]
raise
You can just extend the standard Exception class and add the logger into there.
Like this:
class LoggedException(Exception):
""" An exception that also logs the msg to the given logger. """
def __init__(self, logger: logging.Logger, msg: str):
logger.error(msg)
super().__init__(msg)