xmlrpc.client.Fault 从 rpyc 调用 xmlrpc 方法时
xmlrpc.client.Fault when calling an xmlrpc method from rpyc
我正在尝试构建一个包含两个进程的系统:一个带有 "ping" 方法的 xmlrpc 服务器和一个 QCoreApplication 中间件。中间件有一个连接到 xmlrpc 服务器的 xmlrpc 客户端。中间件还充当 RPyC 服务器。我想通过 RPyC 连接到中间件,并在服务器上调用 "ping" 方法。
# xmlrpc_server.py
from xmlrpc.server import SimpleXMLRPCServer
class XMLRPCServer(SimpleXMLRPCServer):
def __init__(self, addr=('localhost', 4444)):
super(XMLRPCServer, self).__init__(addr)
self.register_function(self.ping)
def ping(self):
return 'pong'
if __name__ == '__main__':
s = XMLRPCServer()
s.serve_forever()
# middleware.py
import sys
import xmlrpc.client
import rpyc
import rpyc.utils.server
from PyQt5 import Qt
class MiddleWare(Qt.QCoreApplication):
def __init__(self, *args, **kwargs):
super(MiddleWare, self).__init__(*args, **kwargs)
self.xmlrpc_client = xmlrpc.client.ServerProxy('http://localhost:4444')
self.rpyc_server = RPyCServer(port=2222)
self.rpyc_server.start()
def ping(self):
return self.xmlrpc_client.ping()
class RPyCService(rpyc.Service):
def on_connect(self):
self.exposed_application = Qt.QCoreApplication.instance()
class RPyCServer(Qt.QThread):
def __init__(self, port=None):
super(RPyCServer, self).__init__()
self._server = rpyc.utils.server.ThreadedServer(
RPyCService,
port=port,
protocol_config={
'allow_all_attrs': True,
'allow_public_attrs': True,
},
)
self.run = self._server.start
if __name__ == '__main__':
mw = MiddleWare(sys.argv)
sys.exit(mw.exec_())
$ python3 xmlrpc_server.py &
[1] 5785
$ python3 middleware.py &
[2] 5986
$ python3
Python 3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import rpyc
>>> conn = rpyc.connect('localhost', 2222, config={'allow_all_attrs': True})
>>> conn.root.application.ping()
'pong'
>>> conn.root.application.xmlrpc_client.ping()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3/dist-packages/rpyc/core/netref.py", line 199, in __call__
return syncreq(_self, consts.HANDLE_CALL, args, kwargs)
File "/usr/lib/python3/dist-packages/rpyc/core/netref.py", line 72, in syncreq
return conn.sync_request(handler, oid, *args)
File "/usr/lib/python3/dist-packages/rpyc/core/protocol.py", line 523, in sync_request
raise obj
rpyc.core.vinegar/xmlrpc.client.Fault:
========= Remote Traceback (1) =========
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/rpyc/core/protocol.py", line 347, in _dispatch_request
res = self._HANDLERS[handler](self, *args)
File "/usr/lib/python3/dist-packages/rpyc/core/protocol.py", line 624, in _handle_call
return self._local_objects[oid](*args, **dict(kwargs))
File "/usr/lib/python3.6/xmlrpc/client.py", line 1112, in __call__
return self.__send(self.__name, args)
File "/usr/lib/python3.6/xmlrpc/client.py", line 1452, in __request
verbose=self.__verbose
File "/usr/lib/python3.6/xmlrpc/client.py", line 1154, in request
return self.single_request(host, handler, request_body, verbose)
File "/usr/lib/python3.6/xmlrpc/client.py", line 1170, in single_request
return self.parse_response(resp)
File "/usr/lib/python3.6/xmlrpc/client.py", line 1342, in parse_response
return u.close()
File "/usr/lib/python3.6/xmlrpc/client.py", line 656, in close
raise Fault(**self._stack[0])
xmlrpc.client.Fault: <Fault 1: '<class \'Exception\'>:method "exposed_ping" is not supported'>
>>>
我希望在调用 conn.root.application.ping() 和直接调用 conn.root.application.xmlrpc_client.ping() 时都能从调用中得到值 'pong',而在第二种情况下显示错误.为什么?
- 正如我所见,对于 rpyc==3.4.4,您必须在注册函数时为其传递一个名称:
from xmlrpc.server import SimpleXMLRPCServer
class XMLRPCServer(SimpleXMLRPCServer):
def __init__(self, addr=("localhost", 4444)):
super(XMLRPCServer, self).__init__(addr)
self.register_function(self.ping, "exposed_ping") # <---
def ping(self):
return "pong"
if __name__ == "__main__":
s = XMLRPCServer()
s.serve_forever()
- 但是在 rpyc==4.0.2 中没有必要这样做但是你有第二个参数给 on_connect:
# ...
class RPyCService(rpyc.Service):
def on_connect(self, conn):
self.exposed_application = Qt.QCoreApplication.instance()
# ...
我能够通过编辑 [protocol_] 配置,添加
来获得想要的结果
'exposed_prefix': ''
# middleware.py
# ...
class RPyCServer(Qt.QThread):
def __init__(self, port=None):
super(RPyCServer, self).__init__()
self._server = rpyc.utils.server.ThreadedServer(
RPyCService,
port=port,
protocol_config={
'allow_all_attrs': True,
'exposed_prefix': '',
},
)
self.run = self._server.start
# ...
$ python3
Python 3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import rpyc
>>> conn = rpyc.connect('localhost', 2222, config={'allow_all_attrs': True, 'exposed_prefix': ''})
>>> conn.root.application.ping()
'pong'
>>> conn.root.application.xmlrpc_client.ping()
'pong'
>>>
我正在尝试构建一个包含两个进程的系统:一个带有 "ping" 方法的 xmlrpc 服务器和一个 QCoreApplication 中间件。中间件有一个连接到 xmlrpc 服务器的 xmlrpc 客户端。中间件还充当 RPyC 服务器。我想通过 RPyC 连接到中间件,并在服务器上调用 "ping" 方法。
# xmlrpc_server.py
from xmlrpc.server import SimpleXMLRPCServer
class XMLRPCServer(SimpleXMLRPCServer):
def __init__(self, addr=('localhost', 4444)):
super(XMLRPCServer, self).__init__(addr)
self.register_function(self.ping)
def ping(self):
return 'pong'
if __name__ == '__main__':
s = XMLRPCServer()
s.serve_forever()
# middleware.py
import sys
import xmlrpc.client
import rpyc
import rpyc.utils.server
from PyQt5 import Qt
class MiddleWare(Qt.QCoreApplication):
def __init__(self, *args, **kwargs):
super(MiddleWare, self).__init__(*args, **kwargs)
self.xmlrpc_client = xmlrpc.client.ServerProxy('http://localhost:4444')
self.rpyc_server = RPyCServer(port=2222)
self.rpyc_server.start()
def ping(self):
return self.xmlrpc_client.ping()
class RPyCService(rpyc.Service):
def on_connect(self):
self.exposed_application = Qt.QCoreApplication.instance()
class RPyCServer(Qt.QThread):
def __init__(self, port=None):
super(RPyCServer, self).__init__()
self._server = rpyc.utils.server.ThreadedServer(
RPyCService,
port=port,
protocol_config={
'allow_all_attrs': True,
'allow_public_attrs': True,
},
)
self.run = self._server.start
if __name__ == '__main__':
mw = MiddleWare(sys.argv)
sys.exit(mw.exec_())
$ python3 xmlrpc_server.py &
[1] 5785
$ python3 middleware.py &
[2] 5986
$ python3
Python 3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import rpyc
>>> conn = rpyc.connect('localhost', 2222, config={'allow_all_attrs': True})
>>> conn.root.application.ping()
'pong'
>>> conn.root.application.xmlrpc_client.ping()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3/dist-packages/rpyc/core/netref.py", line 199, in __call__
return syncreq(_self, consts.HANDLE_CALL, args, kwargs)
File "/usr/lib/python3/dist-packages/rpyc/core/netref.py", line 72, in syncreq
return conn.sync_request(handler, oid, *args)
File "/usr/lib/python3/dist-packages/rpyc/core/protocol.py", line 523, in sync_request
raise obj
rpyc.core.vinegar/xmlrpc.client.Fault:
========= Remote Traceback (1) =========
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/rpyc/core/protocol.py", line 347, in _dispatch_request
res = self._HANDLERS[handler](self, *args)
File "/usr/lib/python3/dist-packages/rpyc/core/protocol.py", line 624, in _handle_call
return self._local_objects[oid](*args, **dict(kwargs))
File "/usr/lib/python3.6/xmlrpc/client.py", line 1112, in __call__
return self.__send(self.__name, args)
File "/usr/lib/python3.6/xmlrpc/client.py", line 1452, in __request
verbose=self.__verbose
File "/usr/lib/python3.6/xmlrpc/client.py", line 1154, in request
return self.single_request(host, handler, request_body, verbose)
File "/usr/lib/python3.6/xmlrpc/client.py", line 1170, in single_request
return self.parse_response(resp)
File "/usr/lib/python3.6/xmlrpc/client.py", line 1342, in parse_response
return u.close()
File "/usr/lib/python3.6/xmlrpc/client.py", line 656, in close
raise Fault(**self._stack[0])
xmlrpc.client.Fault: <Fault 1: '<class \'Exception\'>:method "exposed_ping" is not supported'>
>>>
我希望在调用 conn.root.application.ping() 和直接调用 conn.root.application.xmlrpc_client.ping() 时都能从调用中得到值 'pong',而在第二种情况下显示错误.为什么?
- 正如我所见,对于 rpyc==3.4.4,您必须在注册函数时为其传递一个名称:
from xmlrpc.server import SimpleXMLRPCServer
class XMLRPCServer(SimpleXMLRPCServer):
def __init__(self, addr=("localhost", 4444)):
super(XMLRPCServer, self).__init__(addr)
self.register_function(self.ping, "exposed_ping") # <---
def ping(self):
return "pong"
if __name__ == "__main__":
s = XMLRPCServer()
s.serve_forever()
- 但是在 rpyc==4.0.2 中没有必要这样做但是你有第二个参数给 on_connect:
# ...
class RPyCService(rpyc.Service):
def on_connect(self, conn):
self.exposed_application = Qt.QCoreApplication.instance()
# ...
我能够通过编辑 [protocol_] 配置,添加
来获得想要的结果'exposed_prefix': ''
# middleware.py
# ...
class RPyCServer(Qt.QThread):
def __init__(self, port=None):
super(RPyCServer, self).__init__()
self._server = rpyc.utils.server.ThreadedServer(
RPyCService,
port=port,
protocol_config={
'allow_all_attrs': True,
'exposed_prefix': '',
},
)
self.run = self._server.start
# ...
$ python3
Python 3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import rpyc
>>> conn = rpyc.connect('localhost', 2222, config={'allow_all_attrs': True, 'exposed_prefix': ''})
>>> conn.root.application.ping()
'pong'
>>> conn.root.application.xmlrpc_client.ping()
'pong'
>>>