I am trying to pickle a namedtuple
:
from collections import namedtuple
import cPickle
class Foo:
Bar = namedtuple('Bar', ['x', 'y'])
def baz(self):
s = set()
s.add(Foo.Bar(x=2, y=3))
print cPickle.dumps(s)
if __name__ == '__main__':
f = Foo()
f.baz()
This produces the following output:
Traceback (most recent call last):
File "scratch.py", line 15, in <module>
f.baz()
File "scratch.py", line 11, in baz
print cPickle.dumps(s)
cPickle.PicklingError: Can't pickle <class '__main__.Bar'>: attribute lookup __main__.Bar failed
What am I doing wrong? Is the problem that Bar
is a member of Foo
? (Moving the definition of Bar
to the top level solves the problem, although I'm still curious why this happens.)
Yes, the fact that it's a class member is a problem:
>>> class Foo():
... Bar = namedtuple('Bar', ['x','y'])
... def baz(self):
... b = Foo.Bar(x=2, y=3)
... print(type(b))
...
>>> a = Foo()
>>> a.baz()
<class '__main__.Bar'>
The problem is that when namedtuple()
returns a type object, it isn't aware of the fact that it's being assigned to a class member - and thus, it tells the type object that its type name should be __main__.Bar
, even though it should really be __main__.Foo.Bar
.