Browse Source

Document how to create pickleable exceptions. Closes #401

Ask Solem 13 years ago
parent
commit
e6f2abe4bf
1 changed files with 58 additions and 0 deletions
  1. 58 0
      docs/userguide/tasks.rst

+ 58 - 0
docs/userguide/tasks.rst

@@ -658,6 +658,64 @@ aware of this state that the task is currently in progress, and also where
 it is in the process by having `current` and `total` counts as part of the
 state metadata.  This can then be used to create e.g. progress bars.
 
+.. _pickling_exceptions:
+
+Creating pickleable exceptions
+------------------------------
+
+A little known Python fact is that exceptions must behave a certain
+way to support being pickled.
+
+Tasks that raises exceptions that are not pickleable will not work
+properly when Pickle is used as the serializer.
+
+To make sure that your exceptions are pickleable the exception
+*MUST* provide the original arguments it was instantiated
+with in its ``.args`` attribute.  The simplest way
+to ensure this is to have the exception call ``Exception.__init__``.
+
+Let's look at some examples that work, and one that doesn't:
+
+.. code-block:: python
+
+
+    # OK:
+    class HttpError(Exception):
+        pass
+
+    # BAD:
+    class HttpError(Exception):
+
+        def __init__(self, status_code):
+            self.status_code = status_code
+
+    # OK:
+    class HttpError(Exception):
+
+        def __init__(self, status_code):
+            self.status_code = status_code
+            Exception.__init__(self, status_code)  # <-- REQUIRED
+
+
+So the rule is:
+For any exception that supports custom arguments ``*args``,
+``Exception.__init__(self, *args)`` must be used.
+
+There is no special support for *keyword arguments*, so if you
+want to preserve keyword arguments when the exception is unpickled
+you have to pass them as regular args:
+
+.. code-block:: python
+
+    class HttpError(Exception):
+
+        def __init__(self, status_code, headers=None, body=None):
+            self.status_code = status_code
+            self.headers = headers
+            self.body = body
+
+            super(Exception, self).__init__(status_code, headers, body)
+
 .. _task-custom-classes:
 
 Creating custom task classes