Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: Is it bad form to raise exceptions within __init__?

People also ask

Can you raise an exception in constructor Python?

1 Answer. Raising exceptions within __init__() is absolutely fine. There's no other good way to indicate the error condition within a constructor, and there are many hundreds of examples in the standard library where building an object can raise an exception. The error class is to raise.

Does raising an exception stop the program Python?

except block is completed and the program will proceed. However, if an exception is raised in the try clause, Python will stop executing any more code in that clause, and pass the exception to the except clause to see if this particular error is handled there.

What are the problems if the exception is raised?

When an exception is raised, no further statements in the current block of code are executed. Unless the exception is handled (described below), the interpreter will return directly to the interactive read-eval-print loop, or terminate entirely if Python was started with a file argument.

When should you raise exceptions?

Exceptions should be used for exceptional situations outside of the normal logic of a program. In the example program an out of range value is likely to be fairly common and should be dealt with using normal if-else type logic. (See the programming exercises.)


Raising exceptions within __init__() is absolutely fine. There's no other good way to indicate an error condition within an initializer, and there are many hundreds of examples in the standard library where initializing an object can raise an exception.

The error class to raise, of course, is up to you. ValueError is best if the initializer was passed an invalid parameter.


It's true that the only proper way to indicate an error in a constructor is raising an exception. That is why in C++ and in other object-oriented languages that have been designed with exception safety in mind, the destructor is not called if an exception is thrown in the constructor of an object (meaning that the initialization of the object is incomplete). This is often not the case in scripting languages, such as Python. For example, the following code throws an AttributeError if socket.connect() fails:

class NetworkInterface:
    def __init__(self, address)
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.connect(address)
        self.stream = self.socket.makefile()

    def __del__(self)
        self.stream.close()
        self.socket.close()

The reason is that the destructor of the incomplete object is called after the connection attempt has failed, before the stream attribute has been initialized. You shouldn't avoid throwing exceptions from constructors, I'm just saying that it's difficult to write fully exception safe code in Python. Some Python developers avoid using destructors altogether, but that's a matter of another debate.


I don't see any reason that it should be bad form.

On the contrary, one of the things exceptions are known for doing well, as opposed to returning error codes, is that error codes usually can't be returned by constructors. So at least in languages like C++, raising exceptions is the only way to signal errors.


The standard library says:

>>> f = file("notexisting.txt")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: 'notexisting.txt'

Also I don't really see any reason why it should be considered bad form.


I should think it is the perfect case for the built-in ValueError exception.


I concur with all of the above.

There's really no other way to signal that something went wrong in the initialisation of an object other than raising an exception.

In most programs classes where the state of a class is wholly dependant on the inputs to that class we might expect some kind of ValueError or TypeError to be raised.

Classes with side-effects (e.g. one which does networking or graphics) might raise an error in init if (for example) the network device is unavailable or the canvas object cannot be written to. This sounds sensible to me because often you want to know about failure conditions as soon as possible.