Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 610
kker neo Avatar asked Nov 04 '14 11:11

kker neo


People also ask

Is it good practice to use try-except in Python?

The reason to use try/except is when you have a code block to execute that will sometimes run correctly and sometimes not, depending on conditions you can't foresee at the time you're writing the code.

Why is using a try-except block effective?

What is the reason for the try-except-else to exist? A try block allows you to handle an expected error. The except block should only catch exceptions you are prepared to handle. If you handle an unexpected error, your code may do the wrong thing and hide bugs.

What can I use instead of try and except in Python?

If the situation satisfies the above conditions, you don't have to use try ... except ... to handle the exceptions. Instead, the Python built-in library contextlib provides a function called suppress to handle this more elegantly.

How do you reraise the same exception in Python?

Reraise the current exception Sometimes, you want to log an exception and raise the same exception again. In this case, you can use the raise statement without specifying the exception object. If you pass zero to the second argument of the division() function, the ZeroDivisionError exception will occur.


2 Answers

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.

like image 149
jonrsharpe Avatar answered Oct 21 '22 16:10

jonrsharpe


'error occur' only gets printed once, for the entire class.

You probably expected it to get run for each instance of the class that was created.

For that to happen, put it in the __init__ function,

class AError(Exception):
    def __init__(self):
        print 'error occur'

__init__ is called when an instance of AError is created.

like image 27
Paul Draper Avatar answered Oct 21 '22 15:10

Paul Draper