2012-03-11 38 views
3

我想使用Pyro与现有的一组涉及工厂模式的类,即类A的对象(通常只有一个这样的对象)用于实例化B类的对象(可以有一个任意数字这些)通过工厂方法。所以,我将类A的一个对象公开为Pyro代理对象。如何使用Pyro代理对象作为工厂?

我已经扩展了Pyro introductory sample code以大致反映我正在尝试做什么。服务器端的代码如下:

# saved as greeting.py 
import Pyro4 
import socket 

class NewObj: 
    func_count = None 
    def __init__(self): 
    print "{0} ctor".format(self) 
     func_count = 0 
    def __del__(self): 
    print "{0} dtor".format(self) 
    def func(self): 
    print "{0} func call {1}".format(self, self.func_count) 
    self.func_count += 1 

class GreetingMaker(object): 
    def __init__(self): 
    print "{0} ctor".format(self) 
    def __del__(self): 
    print "{0} dtor".format(self) 
    def get_fortune(self, name): 
    print "getting fortune" 
     return "Hello, {0}. Here is your fortune message:\n" \ 
       "Behold the warranty -- the bold print giveth and the fine print taketh away.".format(name) 
    def make_obj(self): 
    return NewObj() 

greeting_maker=GreetingMaker() 

daemon=Pyro4.Daemon(host=socket.gethostbyname(socket.gethostname()), port=8080)          # make a Pyro daemon 
uri=daemon.register(greeting_maker, "foo") # register the greeting object as a Pyro object 

print "Ready. Object uri =", uri   # print the uri so we can use it in the client later 
daemon.requestLoop()      # start the event loop of the server to wait for calls 

客户端代码也稍有改变:

# saved as client.py 
import Pyro4 

uri="PYRO:[email protected]:8080" 
name="foo" 

greeting_maker=Pyro4.Proxy(uri)   # get a Pyro proxy to the greeting object 
print greeting_maker.get_fortune(name) # call method normally 
print greeting_maker.make_obj() 

我的目的是能够创造的NewObj情况下,对他们只是操纵我可以在客户端操纵GreetingMaker的实例,但看起来好像是在调用make_obj方法时,在服务器端创建NewObj,立即超出范围并因此被垃圾收集。

这是输出是什么样子的,服务器端:

<__main__.GreetingMaker object at 0x2aed47e01110> ctor 
/usr/lib/python2.6/site-packages/Pyro4-4.12-py2.6.egg/Pyro4/core.py:152: UserWarning: HMAC_KEY not set, protocol data may not be secure 
    warnings.warn("HMAC_KEY not set, protocol data may not be secure") 
Ready. Object uri = PYRO:[email protected]:8080 
getting fortune 
<__main__.NewObj instance at 0x175c8098> ctor 
<__main__.NewObj instance at 0x175c8098> dtor 

...和客户端:

/usr/local/lib/python2.6/dist-packages/Pyro4-4.12-py2.6.egg/Pyro4/core.py:152: UserWarning: HMAC_KEY not set, protocol data may not be secure 
    warnings.warn("HMAC_KEY not set, protocol data may not be secure") 
Hello, foo. Here is your fortune message: 
Behold the warranty -- the bold print giveth and the fine print taketh away. 
Traceback (most recent call last): 
    File "client.py", line 9, in <module> 
    print greeting_maker.make_obj() 
    File "/usr/local/lib/python2.6/dist-packages/Pyro4-4.12-py2.6.egg/Pyro4/core.py", line 146, in __call__ 
    return self.__send(self.__name, args, kwargs) 
    File "/usr/local/lib/python2.6/dist-packages/Pyro4-4.12-py2.6.egg/Pyro4/core.py", line 269, in _pyroInvoke 
    data=self._pyroSerializer.deserialize(data, compressed=flags & MessageFactory.FLAGS_COMPRESSED) 
    File "/usr/local/lib/python2.6/dist-packages/Pyro4-4.12-py2.6.egg/Pyro4/util.py", line 146, in deserialize 
    return self.pickle.loads(data) 
AttributeError: 'module' object has no attribute 'NewObj' 

我怀疑我能解决这个问题,破解由拥有工厂类(即GreetingMaker)保留对它创建的每个NewObj的引用,并添加某种清理方法......但这真的有必要吗?我在Pyro中错过了哪些可以帮助我实现的东西?

(编辑为清楚起见)

回答

0

这里的问题是,pyro泡菜NewObj对象在服务器端,但它不能unpickle它在客户端,因为NewObj实现是未知的客户端。

来解决这个问题,将是创建一个名为第三模块,例如new_obj.py并在此之后,如下所示的服务器端和客户端导入的方法之一:

from new_obj import NewObj 

这将让客户端取消NewObj实例并使用它。无论如何,请注意,这将是一个真实的NewObj对象生活在客户端,而不是代理服务器上的对象。

0

我最近遇到了this feature,我正在使用它。对于使用类似工厂模式的代码至关重要。

火焰兵服务器

class Foo(object): 
    def __init__(self, x=5): 
     self.x = x 

class Server(object): 
    def build_foo(self, x=5): 
     foo = Foo(x) 
     # This line will register your foo instance as its own proxy 
     self._pyroDaemon.register(foo) 
     # Returning foo here returns the proxy, not the actual foo 
     return foo 

#... 
uri = daemon.register(Server()) # In the later versions, just use Server, not Server() 
#...