== Python modules should not reinvent _OSError_ In light of [[yesterday's entry PythonEINTR]], here is one of my new rules for Python modules, especially extension modules written in C: > If you're going to raise an exception because a system call failed, > don't make up a new exception for it. Raise either _IOError_ or > _OSError_ themselves. [[Every deviation SocketModuleIrritations]] from this causes annoyances for Python programmers. This is especially visible in [[the situation with signals and _EINTR_ PythonEINTR]], where I really do not want to be rewriting the same code over and over again with different exception classes (or worse, writing different code because you decided to hide _errno_ somewhere new in your exception). A corollary to this is that if for some reason you absolutely have to raise a new exception, you should make it duck typing compatible with _OSError_ (see [[here http://docs.python.org/library/exceptions.html#exceptions.EnvironmentError]] for what that requires). But really, you don't have to, especially because Python code can raise real _OSError_ exceptions. (Please do not get creative with the error message for _OSError_ instances that you create yourself in Python code. If it is not exactly the _strerror()_ of the _errno_, you are doing it wrong.) Extension modules written in C have no excuse, because the Python C API makes it [[very easy http://docs.python.org/c-api/exceptions.html#PyErr_SetFromErrno]] to do the right thing (and reusing _OSError_ saves you from having to create your own C level exception object). Alas, the standard Python exception modules are just overflowing with bad examples, where people make up a new exception instead of reusing _OSError_ or _IOError_. (This is sort of the reverse corollary of [[not using _IOError_ for things that aren't system call errors LeaveIOErrorAlone]].) === Sidebar: to wrap or not to wrap I'm aware that this looks inconsistent with [[my views on not wrapping exceptions WrappingExceptions]]. The difference to me is if you are essentially wrapping a system call and directly exposing _errno_, you should be using the standard way of doing that, which is an EnvironmentError exception (or should be). If the system call's failure is just an internal implementation detail, you should wrap the problem up in your own exception to expose the high level issue. (This is the difference between 'cannot resolve hostname, nameserver not available' and '_sendto()_ failed'. A DNS module that returned the latter would be technically correct but not useful.)