Identify the exception to be used from the traceback - python

I want to catch an exception when user fails login due to wrong password .
So i make a function using imaplib .I enter a wrong password and get a traceback with error details.
Now my question is actually general.How do you identify the exception we have to mention in our "try and except" body from the error messages?
These is what I got->
>>> count("testarc31#gmail.com","Xbox#36")
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
count("testarc31#gmail.com","Xbox#36")
File "E:\Arindam\py_progs\Mail Notifier\0.0.19\Mail.py", line 24, in count
obj.login(m,p)
File "C:\Python27\lib\imaplib.py", line 500, in login
raise self.error(dat[-1])
error: [AUTHENTICATIONFAILED] Invalid credentials (Failure)
If i want to make a try and except,what will i mention in the exception part?
try:
login(mail,pass):
except ????:
something
Question :
1) What will be ???? here . Can it be deduced directly from the error report?
2) Is there a basic idea to identify what is the exception we have to use from each error we get ?

You want to use something like this:
try:
..code that might raise an exception...
except ExceptionType, e:
...do something...
In your case, that probably want this:
try:
login(mail,pass)
except imaplib.IMAP4.error, e:
print "Ouch -- an error from imaplib!"
To identify the type of an exception, you can look at its exception message. In this case it's just "error" -- unfortunately the module name is not included. You can get a better idea of exactly where it comes from by doing:
try:
login(mail,pass)
except Exception, e:
print type(e)

Related

Why does my message for exception not change with my if statement

I currently have the following code which throws an error on exception just how i want:
try:
something ....
except Exception as e:
print(
'You have encountered the following in the main function \n ERROR: {}'.format(e))
However in some cases if I get a specific exception such as:
invalid literal for int() with base 10: ''
I want to change the message of e in the exception to what i want.. how would i go about this?
If e == "invalid literal for int() with base 10: ''":
e = 'my new message'
print(e)
but it doesnt seem to be working
Try catching the type of error instead of parsing the text of the error.
More info can be found at Handling Exceptions section of Python help but to be fully thorough (because I feel dumb for initially answering a Python question in C#) you can sort out what exception type you're looking for with something like this:
>>> # Create the error
>>> int('3.6')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '3.6'
Where ValueError is the error type you need to catch.
More realistically, you can incorporate figuring it your uncaught error types into your program and (hopefully) identify them during testing:
>>> try:
... # something ....
... int('3.6') # for the example, we'll generate error on purpose
... # Assume we've already figured out what to do with these 3 errors
... except (RuntimeError, TypeError, NameError):
... print("We know what to do with these errors")
... # Our generic except to catch unhandled errors.
... except:
... print("Unhandled error: {0}".format(err))
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ValueError: invalid literal for int() with base 10: '3.6'
Once you identify a new error type, add a specific handler for it:
>>> try:
... # something ....
... int('3.6')
... except (RuntimeError, TypeError, NameError):
... print("We know what to do with these errors")
... # The newly added handler for ValueError type
... except ValueError:
... print("And now we know what to do with a ValueError")
... print("My new message")
... except:
... print("Unhandled error: {0}".format(err))
And now we know what to do with a ValueError
My new message
Original (completely useless) answer kept here for posterity (and so the comments make sense)...
Try catching the type of error instead of parsing the text of the error.
e.g.
catch (FileNotFoundException e)
{
// FileNotFoundExceptions are handled here.
}
catch (IOException e)
{
// Extract some information from this exception, and then
// throw it to the parent method.
if (e.Source != null)
Console.WriteLine("IOException source: {0}", e.Source);
throw;
}
which is copied directly from here:
Microsoft try-catch (C# Reference)

How to get the line number on which exception or error occurred in Python?

I have a Django ORM query like this:
try:
specialization_object = Specialization.objects.get(name="My Test Specialization")
except Exception as ex:
print(ex)
When there occurs an exception then it prints "Specialization matching query does not exist.", but it does not print the line number. How can I trace the line number on which the exception or error occurred?
try this:
import logging
logger = logging.getLogger(__name__)
try:
specialization_object = Specialization.objects.get(name="My Test Specialization")
except Exception as ex:
logger.info(ex, exc_info=True) # exc_info will add traceback
further reading see here
If you can't for any reason use logging, There's the standard package traceback, and you can do something like:
traceback.print_exc(file=sys.stdout)
I have figured out a simple solution just now:
import traceback
try:
specialization_object = Specialization.objects.get(name="My Test Specialization")
except Exception as ex:
print(traceback.format_exc())

Error messages in EAFP style

"It's easier to ask for forgiveness than permission", or EAFP, is a common style in Python, where the coder writes code expecting an error and uses the error handling for expected flow control.
The problem I often find is that this can lead to confusing error messages. Consider this example.
some_dict = {} # oops a bug, this should have 'expected key'
try:
some_dict['optional key'] # expected error
except KeyError:
some_dict['expected key'] # unexpected error
Which yields:
Traceback (most recent call last):
File "eafp.py", line 4, in <module>
some_dict['optional key'] # expected error
KeyError: 'optional key'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "eafp.py", line 6, in <module>
some_dict['expected key'] # unexpected error
KeyError: 'expected key'
Specifically, the unexpected error message references the expected one. This is a trivial example, but in some situations the first error may be completely expected and un-noteworthy, but seems closely related to the real cause of the error and can cause some confusion.
My question is how best to handle this type of issue. Can the first error message be suppressed? Or modified to something less conspicuous?
For any wondering, I have ended up using the following (rather obvious) solution to remind myself when debugging.
import logging
logger = logging.getLogger(__name__)
some_dict = {} # oops a bug, this should have 'expected key'
try:
some_dict['optional key'] # expected error
except KeyError as err:
logger.info('Expected Error: %s', err)
some_dict['expected key'] # unexpected error

Safest way to open a file in python 3.4

I was expecting the following would work but PyDev is returning an error:
try fh = open(myFile):
logging.info("success")
except Exception as e:
logging.critical("failed because:")
logging.critical(e)
gives
Encountered "fh" at line 237, column 5. Was expecting: ":"...
I've looked around and cannot find a safe way to open a filehandle for reading in Python 3.4 and report errors properly. Can someone point me in the correct direction please?
You misplaced the :; it comes directly after try; it is better to put that on its own, separate line:
try:
fh = open(myFile)
logging.info("success")
except Exception as e:
logging.critical("failed because:")
logging.critical(e)
You placed the : after the open() call instead.
Instead of passing in e as a separate argument, you can tell logging to pick up the exception automatically:
try:
fh = open(myFile)
logging.info("success")
except Exception:
logging.critical("failed because:", exc_info=True)
and a full traceback will be included in the log. This is what the logging.exception() function does; it'll call logging.error() with exc_info set to true, producing a message at log level ERROR plus a traceback.

Raise two errors at the same time

Is there any way to raise two errors at the same time by using try and except?
For example, ValueError and KeyError.
How do I do that?
The question asks how to RAISE multiple errors not catch multiple errors.
Strictly speaking you can't raise multiple exceptions but you could raise an object that contains multiple exceptions.
raise Exception(
[
Exception("bad"),
Exception("really bad"),
Exception("really really bad"),
]
)
Question: Why would you ever want to do this?
Answer: In a loop when you want to raise an error but process the loop to completion.
For example when unit-testing with unittest2 you might want to raise an exception and keep processing then raise all of the errors at the end. This way you can see all of the errors at once.
def test_me(self):
errors = []
for modulation in self.modulations:
logging.info('Testing modulation = {modulation}'.format(**locals()))
self.digitalModulation().set('value', modulation)
reply = self.getReply()
try:
self._test_nodeValue(reply, self.digitalModulation())
except Exception as e:
errors.append(e)
if errors:
raise Exception(errors)
Python 3.11
Starting with 3.11 you can use ExceptionGroup to raise multiple exceptions.
raise ExceptionGroup("this was bad",
[
Exception("bad"),
Exception("really bad"),
Exception("really really bad"),
]
)
You could raise an error which inherits from both ValueError and KeyError. It would get caught by a catch block for either.
class MyError(ValueError, KeyError):
...
Yes, you can handle more than one error, either using
try:
# your code here
except (ValueError, KeyError) as e:
# catch it, the exception is accessable via the variable e
Or, directly add two "ways" of handling different errors:
try:
# your code here
except ValueError as e:
# catch it, the exception is accessable via the variable e
except KeyError as e:
# catch it, the exception is accessable via the variable e
You may also leave out the "e" variable.
Checkout the documentation: http://docs.python.org/tutorial/errors.html#handling-exceptions
The solution from #shrewmouse still requires to choose an exception class to wrap the caught exceptions.
Following solution uses Exception Chaining via finally to execute code after one exception occurs
We don't need to know beforehand, what exceptions occur
Note that only the first exception that occurs can be detected from the caller via except
if this is a problem, use #Collin's solution above to inherit from all collected exceptions
You'll see the exceptions separated by:
"During handling of the above exception, another exception occurred:"
def raise_multiple(errors):
if not errors: # list emptied, recursion ends
return
try:
raise errors.pop() # pop removes list entries
finally:
raise_multiple(errors) # recursion
If you have a task that needs to be done for each element of a list, you don't need to collect the Exceptions beforehand. Here's an example for multiple file deletion with multiple error reporting:
def delete_multiple(files):
if not files:
return
try:
os.remove(files.pop())
finally:
delete_multiple(files)
PS:
Tested with Python 3.8.5
To print full traceback per exception have a look at traceback.print_exc
The original question is answered since years. But as this page is the top search result for "python raise multiple" I share my approach to fill an (IMHO relevant) gap in the solution spectrum.
try :
pass
except (ValueError,KeyError):
pass
read more about Handling exceptions
You can Raise more than one exception like this:
try:
i = 0
j = 1 / i
except ZeroDivisionError:
try:
i = 'j'
j = 4 + i
except TypeError:
raise ValueError
NOTE: it may be that only the ValueError is raised but this error message seems right:
Traceback (most recent call last):
File "<pyshell#9>", line 3, in <module>
j = 1 / i
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<pyshell#9>", line 7, in <module>
j = 4 + i
TypeError: unsupported operand type(s) for +: 'int' and 'str'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<pyshell#9>", line 9, in <module>
raise ValueError
ValueError

Categories