You can not pickle an xml.etree Element

Yes that is right you will get an error that looks like this
PicklingError: Can't pickle <function copyelement at 0x226d140>: it's not found as
__main__.copyelement
Great how pickle doesn't tell you that it is an xml.etree.Element that is causing the problem or what this element is attached to.
I have been using the multiprocessing module that internally uses pickle to transfer inputs and outputs between processes and it will fail with an even more cryptic message if there is an Element object somewhere in the inputs or outputs.
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/lib/python2.7/multiprocessing/pool.py", line 310, in _handle_tasks
put(task)
TypeError: expected string or Unicode object, NoneType found
To find this problem I replaced pool.map() with map() and pool.apply_async() with apply. Then I used pickle.dumps() on the inputs and outputs to find what was giving the problem.
pickle.dumps(thingee)
pickle.dumps(a)
pickle.dumps(b)
result = apply(my_func, (thingee, a, b))
Then once I had found the offending object I had to subclass pickle.Pickler to get the debugger to jump in at the right spot.
import pickle
class MyPickler (pickle.Pickler):
def save(self, obj):
try:
pickle.Pickler.save(self, obj)
except Exception, e:
import pdb;pdb.set_trace()
Then call it like so
import StringIO
output = StringIO.StringIO()
MyPickler(output).dump(thingee)
And finally I got my answer
Reader Comments