betabug... Sascha Welter

home english | home deutsch | Site Map | Sascha | Kontakt | Pro | Weblog | Wiki

11 January 2008

Who's Pickling Who?

A python hunt

Today I was faced with an error message of "TypeError: can't pickle instancemethod objects" and a traceback that was unusual in that it didn't reference my code at all (see below). Peterbe recently posted a similar problem to the Zope list, but in his case this happened only in a test case. For me it was right inside my code. I found another mention on the python list, which pointed me to the right direction, namely assigning a method as an attribute to an object, when I thought I was assigning a string...

Well, first of all the traceback, which doesn't tell me anything, as it doesn't reference my code at all:

Module ZPublisher.Publish, line 121, in publish
Module Zope2.App.startup, line 240, in commit
Module transaction._manager, line 96, in commit
Module transaction._transaction, line 380, in commit
Module transaction._transaction, line 378, in commit
Module transaction._transaction, line 433, in _commitResources
Module ZODB.Connection, line 484, in commit
Module ZODB.Connection, line 526, in _commit
Module ZODB.Connection, line 553, in _store_objects
Module ZODB.serialize, line 407, in serialize
Module ZODB.serialize, line 416, in _dump
Module copy_reg, line 69, in _reduce_ex

TypeError: can't pickle instancemethod objects

This doesn't really tell me where in my code the problem was. Also sprinkling the code with print statements didn't help either, since the error occurs at the transaction commit, so all the print statements are executed. So my task was to "divide and conquer" another way: I knew which method was called in the browser and I started to break it up by inserting a simple return 'done' in the middle. Moving this line back and forth I located the line that was producing the error.

In my code I was basically doing something like this:

parameter2 = getattr(someobj, 'parameter2', 'default')
# ... snip ...
self.addMySubobject('id', 'parameter1', parameter2, 'parameter3')

This code assumbed that parameter2 was a string attribute - but at some point the underlying code had changed for a subset of possible objects: On those "parameter2" was a method. You can add some object's method to another object in python, but you can't pickle the resulting object.

The solution was to add a simple check in the code:

parameter2 = getattr(someobj, 'parameter2', 'default')
if callable(parameter2):
    parameter2 = parameter2()
# ... and o on

Posted by betabug at 14:44 | Comments (0) | Trackbacks (0)
ch athens
Life in Athens (Greece) for a foreigner from the other side of the mountains. And with an interest in digital life and the feeling of change in a big city. Multilingual English - German - Greek.
Main blog page
Recent Entries
Best of
Some of the most sought after posts, judging from access logs and search engine queries.

Apple & Macintosh:
Security & Privacy:
Misc technical:
Athens for tourists and visitors:
Life in general:
<< There Should Be a Rootkit Detector On It Too... | Main | graffic meets betabug meets graffic >>
There are no comments.
You can trackback to:
There are no trackbacks.