Hi Or,
On Thu, 29 Apr 2010 11:27:16 -0700 (PDT), Or <
or.z...@gmail.com> wrote:
> I've tried this lib for the first time today, yet I can't get it to
> work.
> I've followed the examples, and everything seems find until I try
> sending a class instance over a Channel object.
>
> I've got code similar to this:
> class Tile(object):
> def __init__(self):
> self.x = 2
>
> .....
>
> Eventually, in the server:
>
> player.Send(
> {
> "action": "init",
> "board": Tile()
> }
>
> this fails with
>
> The problem indeed lies in the function encode_dict in rencode.py,
> which simply doesn't support class instances as dictionary values (The
> specific line is 472, compared it to lines like 460, 448)
>
> Seems like it can't read the instance data sent over the pipe.
>
> Is there any way to send and receive class instances?
The underlying encoding algorithm, rencode.py does not do a pickling type
of thing that you need. So there are a few ways to get around that and
"send" your class instance across the network. A basic way do this if your
class
is very simple and only contains Python data types, is to send
tileinstance.__dict__ over the network instead of the Tile() object itself
(where tileinstance = Tile() for example). On the other side you can
initialise a new Tile() object from the received data by doing something
like tileinstance.__dict__ = received_data. This can be suboptimal though,
depending on the structure of your class and what's in it.
If you want more control over exactly what is sent, you could create a
method in Tile() called e.g. network_repr() and from_network_repr(). Those
calls would return a network safe version of the important data inside
Tile() that you want to send, and re-initialise a Tile() instance with
given data on the other side. For example Tile.network_repr() might return
a structure looking like {"x": 5, "y": 10}, and Tile.from_network_data()
might initialise an instance of Tile() with x and y from that dict.
If you have a situation where Tile() also contains some other class like a
Bitmap() which has binary data or something and you want to make sure that
all elements of the class, including other instances of classes embedded
in
it, and their data get sent over the network, then you could try using
Python's cPickle to turn the class into a data-blob and send it as a
string. So you would Pickle() your whole Tile instance and the sent
structure would end up looking like {"action": "newtile", "Tile":
"PICKLED-DATA-BLOB"}. One problem with Pickle is that unpickling pickle
data can be a security risk as someone can inject all kinds of Python code
over the network by modifying the client.
Hope this helps!
Best,
Chris.
-------------------
http://mccormick.cx