I'm trying to run a function on the server with Pyro4. Have a look at the code: ==========================Client======================
import Pyro4
def square(x):
return x**2
remoteServer = Pyro4.Proxy('PYRONAME:server')
print(remoteServer.evaluate(square, 4))
===========================Server==========================
import Pyro4
class Server(object):
def evaluate(self, func, args):
return func(*args)
def main():
server = Server()
Pyro4.Daemon.serveSimple({server: "server"},ns=True)
if __name__ == '__main__':
main()
========================Naming Server========================
import Pyro4
Pyro4.naming.startNSloop()
===========================================================
And got an error: "Pyro4.errors.ConnectionClosedError: receiving: not enough data". Look at the full stack trace below:
Traceback (most recent call last):
File "C:\Users\Alex\Desktop\2.py", line 9, in <module>
print(remoteServer.evaluate(square, 4))
File "C:\Users\Alex\AppData\Roaming\Python\Python34\site-packages\Pyro4\core.py", line 169, in __call__
return self.__send(self.__name, args, kwargs)
File "C:\Users\Alex\AppData\Roaming\Python\Python34\site-packages\Pyro4\core.py", line 380, in _pyroInvoke
msg = message.Message.recv(self._pyroConnection, [message.MSG_RESULT], hmac_key=self._pyroHmacKey)
File "C:\Users\Alex\AppData\Roaming\Python\Python34\site-packages\Pyro4\message.py", line 161, in recv
msg = cls.from_header(connection.recv(cls.header_size))
File "C:\Users\Alex\AppData\Roaming\Python\Python34\site-packages\Pyro4\socketutil.py", line 460, in recv
return receiveData(self.sock, size)
File "C:\Users\Alex\AppData\Roaming\Python\Python34\site-packages\Pyro4\socketutil.py", line 195, in receiveData
raise err
Pyro4.errors.ConnectionClosedError: receiving: not enough data
I want the server executes the function that is passed to a method (function).
PS: Windows7, Python 3.4.1
I've found similar question (How to send a function to a remote Pyro object), but didn't work for me. Tried to use callback decorator @pyro4.callback, but even official example (https://github.com/delmic/Pyro4/tree/master/examples/callback : server2.py, client2.py) didn't work (with python 3.4 and python 2.7) => only message: "server: doing callback 1 to client" is showed and nothing happens.
Thanks
The github repo you're linking to is not the official one. It's a clone (from quite an old version). This is the official repo: https://github.com/irmen/Pyro4
As to your problem: it is not possible to serialize functions and send them over the wire. If you tell Pyro to use pickle as a serialization protocol, you can do more tricks, but pickle still needs to have the module source or bytecodes available on both sides of the connetion.
The reason your client crashes is because the server aborts the connection due to a Pyro protocol error. If you enable the logging it will show up in the server's logfile, something like: "Pyro4.errors.ProtocolError: unsupported serialized class: builtins.function".
Also a tip: you don't have to start the name server using a separate source code file. You can start it directly from the command line.
Lastly, the @pyro4.callback decorator is unrelated, please read http://pythonhosted.org/Pyro4/clientcode.html?highlight=callback#pyro-callbacks for what it is intended for. It influences the way Pyro handles exceptions, nothing more.
edit: note that since Pyro 4.35 this error will be correctly reported back to the client and it will no longer get an aborted connection.