sync_request !
You're not getting an object byValue but rather byRef, this means if you
make a change to the dict on the server it will get reflected on the
client. Even though this some might make sense for calling methods on
the other end, it doesn't for the arguments dict (which is your case).
My solution to this issue was to do pickle.dumps on the client and
pickle.loads on the other end. I know this sucks, but I figured out it's
a good solution, as I don't want modifications on the server to be
reflected on the client.
Rpyc has been designed to be very flexible and I love that, but this
kind of issues are the ones that are hard to work with. Maybe it's time
to drop sync calls and start doing all async? inLineGenerators from
twisted is a nice example on how to make the code look sync while
actually is async. A few weeks ago there was the first PyCon Argentina,
I've been there and someone showed this method, I think it's worth
studying it to make rypc even more robust. The base for this is using
yield when ever the request is going to go through the network.
Manuel
rpyc/core/protocol.py", line 329, in sync_request
raise obj
AttributeError: cannot access 'items'
> rpyc strives to be transparent, i.e., your code should work the same
> on local objects as well as remote ones.
> with @inlineCallbacks, an invocation like this:
>
> c.modules.os.listdir("/")
>
> would look like
> @inlineCallbacks
> def foo():
> r1 = yield c.modules.os # remote-getattr to get module
> r2 = yield r1.listdir # remote-getattr to get function
> r3 = yield r2("/") # remote-invocation of the function
>
> or, more succinctly:
> yield (yield (yield c.modules.os).listdir)("/")
Not totally sure about this. That's because rpyc makes a difference
between sync and async calls. But I'm not such an expert on python to
tell how it should look like.
> bottom line, mixing synchronous and async programming models do not
> play well together.
> either you write your whole program twisted, or you stick with the
> "normal" sync model.
Maybe it's just because of GIL, but this "normal" model you talk about
is not possible on Linux so far. It eventually stops. Specially when you
have a system (which I'm not sure I designed right, sorry I'm an
electronic engineer, not an informatics guy) that uses a sort of
signaling system, where the calls goes all the time from one side to the
other.
Now I had been able to trace all the problems down to the call to
<connection>.root a sync call, that halts the thread when one side is
waiting for the other to return. Maybe rpyc needs a way to define
byReference and byValue variables? For example in a signal system I send
the signal to the remote end and I drop the variable on my side. If the
other side keeps a reference then it makes the local site headache, and
the garbace collector is getting into troubles too.
The "Hackish" solution I found is pickling, but maybe it's time for a
better way? Maybe something like a rpyc.byValue() function? by default
you pass by reference, but if you want you can do it by value? If you
think this sounds good I can try implementing this and creating a patch.
I have many uses for this.
Manuel
For the moment, since I'm working with MongoDB anyway, I'm using it
directly through pymongo to transmit dictionaries. Rpyc is used to get
some datas, like timestamps and so on, and to synchronise operations
of the different serveur accessing collections in MongoDB.
My skill as a programmer is rusty, to say the least... But since my
program will be open, I'll give you a like to the bitbucket repository
when available. :-)
--
Antoine Boegli
software engineer & linux expert
The "Hackish" solution I found is pickling, but maybe it's time for a better way? Maybe something like a rpyc.byValue() function? by default you pass by reference, but if you want you can do it by value? If you think this sounds good I can try implementing this and creating a patch. I have many uses for this.
Ohh right it does it, not the same way I think on how to do it, but it
does it. What about moving this to rpyc.utils.helpers and importing into
rpyc?
Still I would change it, it transmits the remote proxy and then
pickle/unpickle on the local end, what I do is sending the pickled
object as I would transmit any string. What about adding it to brine so
that brine makes this seems less to the other end?.
Something like
A = rpyc.utils.byRef(<object>)
conn.root.somemethod(A)
On the other end you would have:
def exposed_somemethod(A):
print A
And the internals is handled by brine?
Manuel