18

I am new at Python and I'm stuck at this problem. I am trying to compare two "exception objects", example:

try:
    0/0
except Exception as e:
    print e
>> integer division or modulo by zero

try:
    0/0
except Exception as e2:
    print e2
>> integer division or modulo by zero

e == e2
>> False

e is e2
>> False

How should I perform this comparison to obtain a "True"?

What I am trying to do:

class foo():
    def bar(self, oldError = None):
        try:
            return urllib2.urlopen(someString).read()                   
        except urllib2.HTTPError as e:
            if e.code == 400: 
               if e != oldError: print 'Error one'
            else: 
               if e != oldError: print "Error two"
            raise
         except urllib2.URLError as e:
             if e != oldError: print 'Error three'
             raise

class someclass():        
    # at some point this is called as a thread
    def ThreadLoop(self, stopThreadEvent):
        oldError = None
        while not stopThreadEvent.isSet():
            try:
                a = foo().bar(oldError = oldError)
            except Exception as e:
                oldError = e
            stopThreadEvent.wait(3.0)

(probably some syntax error)

Why I am doing that? Because I don't want to print the same error twice

5
  • 1
    What are you actually trying to do here? I have given an answer, but I imagine there is a better way to go about this. Commented Apr 5, 2013 at 21:49
  • I updated the question, your answer was perfect to my (generic) original question, but unfortunately it will not work on my problem (if I have two exceptions of the same type, but different attributes, I need a "true" for equality comparison) Commented Apr 5, 2013 at 22:30
  • 1
    Your description is how mine works. Commented Apr 5, 2013 at 22:32
  • Sorry I'm rephrasing: e1 == e2 -> e1.attributes == e2.attributes AND e1.type == e2.type, e1 != e2 -> e1.attributes != e2.attributes OR e1.type != e2.type [not python, just generic code] Commented Apr 5, 2013 at 22:44
  • 1
    That's the opposite of what you stated. In which case, you want @nneonneo's answer. Commented Apr 5, 2013 at 22:46

3 Answers 3

31

With most exception classes, you can test for functional equality with

type(e) is type(e2) and e.args == e2.args

This tests that their classes are exactly identical, and that they contain the same exception arguments. This may not work for exception classes that don't use args, but to my knowledge, all standard exceptions do.

Sign up to request clarification or add additional context in comments.

11 Comments

I think this is slightly better than Lattyware's answer for the simple reason that this one actually tells you if the exceptions have equivalent arguments, which is not the same as whether they're both instances of the same class. You might have two exceptions of the same class that were raised with different arguments; this gives you more "equivalency" in that regard. My only comment is the same as @Lattyware's below: type() is better than __class__.
As a note, I really dislike the use of e.__class__ here - type() exists for a reason, and if you want the type of an object, it's the way to access it.
@Lattyware: OK, I will use type. Thanks for the tip.
@ChrisKrycho It entirely depends on what the OP wants - I can't think of a situation where you would want to do this, so I don't know if the OP wants equivalency to that level. The OP really needs to explain more about what he wants before anyone could say which answer is preferable.
@Lattyware: What about wanting to test whether two KeyErrors refer to the same missing key? Or whether two IOErrors are actually the same errno? (Yes, there are class-specific ways to do the check, but using .args gives you a nice generic way to do it).
|
7

You want to check the type of the exception:

>>> isinstance(e2, type(e))
True

Note, naturally, this will allow for subclasses - this is a weird thing to do, so I'm not sure what behaviour you are looking for.

1 Comment

FWIW, autopep8 converts type(e) is type(e2) to isinstance(e, type(e2)). It's still probably worth adding another assert with e.args == e2.args though.
0

In this case, comparing the exception message using str() would be useful.

...
        except urllib2.HTTPError as e:
            if e.code == 400: 
                if isinstance(oldError, type(e)) and str(e) != str(oldError): 
                    print 'Error one'
            else: 
                if isinstance(oldError, type(e)) and str(e) != str(oldError): 
                    print "Error two"
            raise
         except urllib2.URLError as e:
             if isinstance(oldError, type(e)) and str(e) != str(oldError): 
                 print 'Error three'
             raise
...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.