Search code examples
pythontry-catchexcept

Confused about try/except with custom Exception


My code:

class AError(Exception):
    print 'error occur'
for i in range(3):
    try:
        print '---oo'
        raise AError
    except AError:
        print 'get AError'
    else:
        print 'going on'
    finally:
        print 'finally'

When I run the above code, the output is this:

error occur
---oo
get AError
finally
---oo
get AError
finally
---oo
get AError
finally

I think the string "error occur" should occur three times, like "---oo", but it only occurs once; why?


Solution

  • To clarify Paul's answer, here's a simple example:

    class Test(object):
    
        print "Class being defined"
    
        def __init__(self):
            print "Instance being created"
    
    
    for _ in range(3):
        t = Test()
    

    The output from this will be:

    Class being defined
    Instance being created
    Instance being created
    Instance being created
    

    Code within the class definition but outside a method definition runs only once, when the class is defined.

    If you want code to run whenever an instance is created, it should be in the __init__ instance method (or, occasionally, the __new__ class method). However, note that if you define __init__ for a subclass, you should probably ensure that it also calls the superclass's __init__:

    class AError(Exception):
    
        def __init__(self, *args, **kwargs):
            Exception.__init__(self, *args, **kwargs) # call the superclass
            print 'error occur' # print your message
    

    This ensures that the subclass supports the arguments for the superclass; in the case of Exception, you can e.g. pass an error message:

    >>> raise AError("Something went wrong.")
    error occur # your message gets printed when the instance is created
    
    Traceback (most recent call last):
      File "<pyshell#11>", line 1, in <module>
        raise AError("Something went wrong.")
    AError: Something went wrong. # the error message passes through to the traceback
    

    For an explanation of the *args, **kwargs syntax, if you aren't familiar with it, see e.g. What does ** (double star) and * (star) do for parameters?. You can also use super to call the superclass methods, see e.g. Understanding Python super() with __init__() methods.