pythonpython-2.7loggingio-redirectionrpyc

Python: remote logging with rpyc


Hi I'm using the rpyc module to connect to a remote machine and execute some stuff on it. In process the remote machine might log some stuff so I need to redirect it to my local machine.

In attempt to redirect the logs I've encountered this weird exception:

import rpyc


c = rpyc.classic.connect("localhost")
l = c.modules["logging"].getLogger("foo")

for h in l.handlers:
    print h

This loop causes an exception to be raised:

2017-03-19 11:38:29,180 - protocol.py    :312  - DEBUG      - Exception caught
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/rpyc-3.2.3-py2.7.egg/rpyc/core/protocol.py", line 302, in _dispatch_request
res = self._HANDLERS[handler](self, *args)
File "/usr/lib/python2.7/site-packages/rpyc-3.2.3-py2.7.egg/rpyc/core/protocol.py", line 560, in _handle_callattr
return self._handle_getattr(oid, name)(*args, **dict(kwargs))
StopIteration

Does anyone sees what I'm doing wrong? Why shouldn't I be able to iterate over l.handlers?


Solution

  • StopIteration is the exception that's raised by python the moment an iterator runs out of elements and the loop that's consuming them should be stopped (normally). It seems that rpyc doesn't recognise the special nature of the StopIteration exception and instead just throws it as an error that crashes the code.

    A solution might be to not iterate over a remote collection, and instead turn it into a local collection first if that is at all possible. You can try the following (although it might very well crash with the same error as before, because converting something into a list also has to iterate over it):

    local_handlers = list(l.handlers)
    for h in local_handlers:
        print(h)
    

    Incidentally, Pyro4 does handle remote iteration correctly, you can loop over remote iterators and also generators just fine. (It does work a bit differently than rpyc though so your code doesn't translate directly)