我有一个类似于下面的远程服务器已经有一个初始化的类,我已经设置了协议配置为允许公共attrs True。
import rpyc
class SharedClass(object):
def __init__(self,string):
print string
def action(self):
print 'i am doing something'
s=SharedClass('hi')
class MyService(rpyc.Service):
def on_connect(self):
pass
def on_disconnect(self):
pass
def exposed_get_shared(self):
return s
if __name__=='__main__:
from rpyc.utils.server import ThreadedServer
t=ThreadedServer(MyService,port=18861,protocol_config={"allow_public_attrs":True})
t.start()
在客户端,如果我尝试直接连接它正在工作,而 当我尝试在函数内部建立连接并返回对象时 我收到了错误
** **客户端
**直接连接**
>>>Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win32
>>>Type "help", "copyright", "credits" or "license" for more information.
>>>conn=rpyc.connect('localhost',18861)
>>>share=getattr(conn.root,'get_shared')
>>>share
<bound method MyService.exposed_get_shared of <__main__.MyService
object at 0x011BA698>>
>>>share=getattr(conn.root,'get_shared')()
>>>share
<__main__.SharedClass object at 0x00B6ED30>
>>>share.action()
i am doing something
如果我尝试在函数中执行此操作,则会出现错误;(
>>>def returnObject(objName, host, port):
... conn = rpyc.connect(host, port)
... print conn
... attr = getattr(conn.root, 'get_' + objName)()
... print attr
... return attr
>>>share=returnObject('shared','localhost',18861)
<rpyc.core.protocol.Connection 'conn2' object at 0x0108AAD0>
<__main__.SharedClass object at 0x00B6ED30>
>>>share
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\site-packages\rpyc\core\netref.py", line 168,
in __repr__
return syncreq(self, consts.HANDLE_REPR)
File "C:\Python27\lib\site-packages\rpyc\core\netref.py", line 69,
in syncreq
return conn().sync_request(handler, oid, *args)
AttributeError: 'NoneType' object has no attribute 'sync_request'
我的目的是在服务器中初始化一个对象,并让许多客户端访问它。初始化的类是线程安全的,因此多个客户端可以使用它。
我意识到我在做这件事时错过了一些东西。
-
Adhithya
答案 0 :(得分:2)
虽然我没有rpyc的实际经验,但是从你的例子看来,唯一真正的区别是当执行returnObject函数时'conn'引用没有被保留,所以我猜这种情况与垃圾收集无关由'conn'引用。稍微修改一下returnObject函数,以便返回'conn'并保留在函数外部,示例似乎就会执行。
>>> import rpyc
>>> def returnObject(objName, host, port):
... conn = rpyc.connect(host, port)
... print conn
... attr = getattr(conn.root, 'get_' + objName)()
... print attr
... return conn, attr
...
>>> conn, share = returnObject('shared', 'localhost', 18861)
<rpyc.core.protocol.Connection 'conn1' object at 0x10b0676d0>
<__main__.SharedClass object at 0x1091ff790>
>>> share
<__main__.SharedClass object at 0x1091ff790>
>>> share.action()
由于我参与了另一个python远程对象解决方案Versile Python的开发,这里只是为了好玩是使用该解决方案的替代实现(需要VPy dev版本0.7.2,下一版本将有一些冲突的API更改)。提供SharedClass访问的远程服务:
from versile.quick import *
from versile.vse.native.python import VPythonObject
VSEResolver.add_imports()
class SharedClass(object):
def action(self):
return u'I am doing something'
shared = SharedClass()
class Gateway(VExternal):
@publish(show=True, ctx=False)
def get_shared(self):
return VPythonObject(shared)
service = VTPService(lambda: Gateway(), auth=None)
service.start()
访问服务的客户端代码:
>>> from versile.quick import *
>>> VSEResolver.add_imports()
>>> gw = VUrl.resolve('vtp://localhost/')
>>> shared = gw.get_shared()
>>> shared._v_activate() # required for activating as remote-python proxy
>>> shared.action()
u'I am doing something'
>>> gw._v_link.shutdown()