python >> Can not dump class object created on runtime

by Chris Rebert » Thu, 11 Jun 2009 07:43:38 GMT

On Wed, Jun 10, 2009 at 7:25 AM, Metal Zong< XXXX@XXXXX.COM > wrote:
> Hello,
>
> Can not dump class object created on runtime.
>
> Is there anybody can help me? Thank.
>
> Following is testing code:
>
> import pickle
> from new import classobj
>
> class A:
> def __str__(self):
> return self.__class__.name
>
> if __name__ == "__main__":
> c = classobj('B', (A, ), {}) # create class obj on runtime
> print c
> print pickle.dumps(c) # get dump string
>
> Bellows are outputs:
>
> __main__.B
> Traceback (most recent call last):
> File "C:\USERS\train\_work\test\test.py", line 11, in <module>
> print pickle.dumps(c)
> File "c:\USERS\train\Python25\lib\pickle.py", line 1366, in dumps
> Pickler(file, protocol).dump(obj)
> File "c:\USERS\train\Python25\lib\pickle.py", line 224, in dump
> self.save(obj)
> File "c:\USERS\train\Python25\lib\pickle.py", line 286, in save
> f(self, obj) # Call unbound method with explicit self
> File "c:\USERS\train\Python25\lib\pickle.py", line 748, in save_global
> (obj, module, name))
> pickle.PicklingError: Can't pickle <class __main__.B at 0x00AF4CF0>: it's
> not found as __main__.B

pickle stores classes by storing their fully-qualified name (eg.
"foo.bar.Baz") and NOT by storing the internal Python structures that
represent the class (as there are apparently various problem
associated with this). So when it unpickles, it just imports the
fully-qualified name normally and returns the result of that.
Since dynamically-created classes have no fully-qualified name, they
can't be stored this way; hence, you get an exception when trying to
pickle.dump() them.

Also, you shouldn't use `classobj` as I believe that's only for
old-style classes, which are being phased out. Its replacement is the
built-in `type` metaclass, which creates new-style classes.

Cheers,
Chris
--
http://blog.rebertia.com

Similar Threads

1. marshal.dumps quadratic growth and marshal.dump not allowing file-like objects

2. Boost.Python create extra functions not in wrapped object

Hi,

I have a python library created by wrapping the C++ library using
Boost.Python, the problem is that the wrappers are not very
pythonic.... so I want to add some methods that do not exist in the C+
+ implementation, that would create a better Python interface.

For example to initialize the data in an object in the library one
must iterate through every point, setting a value for each
individually.  That's the way it works in C++ but in python it would
be nice to instead just have one call that can receive a numpy array
or a tuple. I want to add a call like: setData(array) to the python
object, a call that does not exist in the C++ implementation and then
in the C++ wrappers actually use setData to iterate through the array
and set the values using the normal C++ method, say setValue(index,
value).

Something along the lines of this (initData is not in the constructor
on purpose) C++ object:

class Foo
{
public:
     void initData(int size)
     {
        data = new float[size];
     }; // Create the data array
     void setValue(int index, float value) // Set given value
     {
         data[index] = value;
     }
private:
     float *data;
};


In python however I want to do this:

obj = foo()
ar = array([1,2,3,4,5], dtype=float)

foo.setData(ar)

Or even better:

ar = array([1,2,3,4,5], dtype=float)
obj = foo(ar)

And have it somehow call initData() and setValue() iteration inside
the C++ code of the wrapper.  I've only used SWIG and don't really
know much about Boost, I am not even sure how to label what I am
trying to do.

Can this be done with Boost, without changing the C++ library?

Regards,

Stou

3. creating a similar object from an derived class

4. Python C api: create a new object class

Hello

I have 3 questions, hope someone can help:

1)
How can I create an instance class in Python, currently I do:

class empty:
  pass

Then anytime I want that class (which I treat like a dictionary):

o = empty()
o.myattr = 1
etc....

Is there is a one line syntax to instantiate an instance?

Any other ways than this:
o = new.classobj('object', (), {})

2)

How can I, similarly, create an object "o" in C api:

PyObject *o = what_to_call(....)

....
PyObject_SetAttrString(o, "attrname", py_val)

...

One way I found was first calling PyClass_New() (to create an empty class) 
and then passing the return value to PyInstance_NewRaw to get a new instance 
of that empty class.

Can I achieve the same otherwise?

3)

Given a PyObject* is there is a way to tell if one can call 
PyObject_SetAttrString() on that object w/o getting an error?

For example, before calling a PyObject* one can see if it is callable, but 
can I test if an object supports setattr?

(from C api)

Thank you,

Elias 

5. creating class objects inside methods

6. getting attributes and methods of class without creating object

Suppose I have a class like this -

class myClass(object):

    def __init__(self):
        self.a = 10
        self.b = 20

    def my_method(self,var = 20):
        self.local_var = var

I want to know about its method(__init__ and my_method) and
variables(a,b, local_var) without creating the object of it. I tried
getmembers function of inspect module. But it can do this with an
object of myClass as argument. Like

import inspect
var = myClass()
inspect.getmembers(var)

I have to know about this without creating the object of myClass.
Can anyone help me please?

7. Creating classes and objects more than once?

8. Creating Class Objects in Loop

Hello Folks,
I am reading a CSV file and based on that I am creating TestCase(my
own defined class) objects in a for loop. The problem is each time I
create a new TestCase object in loop, previous objects data is already
copied in that object.

e.g. my sample CSV file is
# -------------------------
hello.pcap, 123, 231
test.pcap, 90, 899
hello2.pcap, 81, 18
# -----------------------

When I print the TestCase elements from returned list I get

(Pdb) print tcLstOrig[0]
Pcap Path: hello.pcap
Sid List: 123, 231, 90, 899, 81, 18,

(Pdb) print tcLstOrig[1]
Pcap Path: test.pcap
Sid List: 123, 231, 90, 899, 81, 18,

(Pdb) print tcLstOrig[2]
Pcap Path: hello2.pcap
Sid List: 123, 231, 90, 899, 81, 18,


Kindly guys advise me on this thing. Function snippet and Class
definition are provided below.

Regards,
Fish

======= Problem Code

The function snippet reading CSV and creating TestCase objects is
[code]
tcLst = []
# CSV file is read in variable 'lines'
def returnTcLst(path):
  fp = open(path)
  lines = fp.readlines()

  for line in lines:
	tc = TestCase()
	i = line.find(",")
	tc.setPcap(line[:i].strip())
	line = line[i+1:]
	line = line + ","
	i = line.find(",")
	while i != -1:
		sid = line[:i].strip()
		tc.appendSid(sid)
		line = line[i+1:]
		i = line.find(",")

	tcLst.append(tc)
	del tc
  return tcLst
[/code]

My TestCase Class is defined as
[code]
class TestCase(object):
	def __init__(self, pcap = None, sids = []):
		self.__Pcap = pcap
		self.__lstSid = sids

	def setPcap(self, path):
		self.__Pcap = path

	def appendSid(self, sid):
		self.__lstSid.append(sid)

	def __str__(self):
		text = "Pcap Path: " + self.__Pcap + "\n"
		text += "Sid List: "
		for sid in self.__lstSid:
			text += sid + ", "
		text += "\n"
		return text
[/code]