# phone num
try:
phone=soup.find("div", "phone-content")
for a in phone:
phone_result= str(a).get_text().strip().encode("utf-8")
print "Phone information:", phone_result
except ValueError:
phone_result="Error"
My program stops when there is a uni-code error but i want to use try except to avoid terminating the program. how can i do it?
I get different types of errors. i want something which just doesnt terminate the loop no matter whatever the error. just i want to skip the part of the loop which has error
By using
try:
...
except:
...
You could always catch every error in your try block attempt. The problem with THAT is that you'll catch even KeyboardInterrupt and SystemExit
However, it's better to catch Errors you're prepared to handle so that you don't hide bugs.
try:
...
except UnicodeError as e:
handle(e)
At a minimum, you should at least be as specific as catching the StandardError.
Demonstrated using your code:
try:
phone=soup.find("div", "phone-content")
for a in phone:
phone_result= str(a).get_text().strip().encode("utf-8")
print "Phone information:", phone_result
except StandardError as e:
phone_result="Error was {0}".format(e)
See the Exception Hierarchy to help you gauge the specificity of your error handling.
http://docs.python.org/2/library/exceptions.html#exception-hierarchy
I think you can try something like this first:
try:
whatever()
except Exception as e:
print e
Then you will get your desired(!) exception [if it already exists], and then change it to except somethingelse
Or you can go for custom exception which will look something like following, but you have raise it where necessary:
class ErrorWithCode(Exception):
def __init__(self, code):
self.code = code
def __str__(self):
return repr(self.code)
Related
tl;dr
How to catch different exceptions of the same type but with different messages?
Situation
In ideal world I would handle exceptions like this:
try:
do_something()
except ExceptionOne:
handle_exception_one()
except ExceptionTwo:
handle_exception_two()
except Exception as e:
print("Other exception: {}".format(e))
But external code that I'm using can can throw, in my usage, two exceptions. Both are ValueErrors but have different message. I'd like to differentiate handling them. This is the approach that I tried to take (for easier presentation of my idea I raise AssertionError):
try:
assert 1 == 2, 'test'
except AssertionError('test'):
print("one")
except AssertionError('AssertionError: test'):
print("two")
except Exception as e:
print("Other exception: {}".format(e))
but this code always goes to the last print() and gives me
Other exception: test
Is there a way to catch exceptions this way? I'm assuming this is possible because Python lets me specify MESSAGE when catching exception ExceptionType('MESSAGE') but in practice I didn't manage to make it work. I also didn't find a definitive answer in the docs.
I would go for something like this:
try:
do_the_thing()
except AssertionError as ae:
if "message A" in ae.value:
process_exception_for_message_A()
elif "message B" in ae.value:
process_exception_for_message_B()
else:
default_exception_precessing()
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!')
I have code that's a bit like this:
try:
# do stuff
except SomeSpecificException as sse:
if sse.some_property == some_special_value:
# handle the exception in a special way
else:
handle_exception_normally()
except:
handle_exception_normally()
I want to catch the specific exception and handle it in a special way, but only if it has a particular property. If it doesn't have that property, I want it to be handled just like any other exception (logging, screaming, etc.)
The code above works, but if possible, I want to avoid repeating handle_exception_normally() (DRY and all that).
Just putting raise in the else clause of the first except block does not work. A parent try block would catch that, but the catch-all clause in the same block will not.
I could nest two try blocks, but it's not very elegant; I'd rather just use
the code I have above.
Is there a better way?
Note that I'm using Python 3.
I would opt for:
try:
# do stuff
except Exception as e:
if e.args[0] == 'Discriminate Exception Here' and sse.some_property == some_special_value:
# handle the exception in a special way
else:
handle_exception_normally()
Moses Koledoye proposed:
try:
# do stuff
except Exception as e:
if getattr(e, 'some_property', None) == some_special_value:
# handle the exception in a special way
else:
handle_exception_normally()
Which is shorter but requires some_special_value to always be != None and attribute to be unique to your exception.
Examples of exception discrimination, with e.args[0]:
try:
5 / 0
except Exception as e:
print(e.args[0])
division by zero
With __class__.__name__:
try:
5 / 0
except Exception as e:
print(e.__class__.__name__)
ZeroDivisionError
With isinstance() (bit more CPU intensive) :
try:
5 / 0
except Exception as e:
isinstance(e, ZeroDivisionError)
True
I understand OP said they do not want to do this, but I'm throwing my lot in with the nested try block. I think it's the most readable way to go about this:
try:
try:
# do stuff
except SomeSpecificException as sse:
if sse.some_property == some_special_value:
# handle the exception in a special way
else:
raise
except:
handle_exception_normally()
I'm wondering if there is a keyword for "all" in python except. I've ran into this seemingly simple problem:
try:
#do stuff
except any as error:
print('error: {err}'.format(err=error))
I know that you can do except: to catch all errors, but I don't know how to add an as keyword to get a printable object. I want to catch any error and be able to get an object for use in printing or something else.
You can catch almost anything this way:
try:
#do stuff
except Exception as error:
print('error: {err}'.format(err=error))
But to catch really everything, you can do this:
import sys
try:
#do stuff
except:
err_type, error, traceback = sys.exc_info()
print('error: {err}'.format(err=error))
Yes, just catch Exception:
except Exception as ex:
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)