2012-03-11 3 views
3

Pyro를 Factory 패턴과 관련된 기존 클래스 집합, 즉 클래스 A의 객체 (일반적으로 이들 중 하나만있을 것입니다)가 클래스 B의 객체를 인스턴스화하는 데 사용됩니다 (임의의 숫자가있을 수 있음) 이들 중 하나)을 팩토리 메소드를 통해 호출합니다. 그래서 Class 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의 인스턴스를 생성하고 I로 단지를 조작 할 수있을 것입니다 클라이언트 측에서 GreetingMaker의 인스턴스를 조작 할 수 있지만 어떤 일이 발생하는지는 make_obj 메서드가 호출되면 서버 측에서 NewObj이 생성되고 즉시 범위를 벗어나 가비지 수집됩니다. 공장을함으로써

/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' 

내가이 문제를 해결 해킹 수 의심 :

<__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 

... 그리고 클라이언트 측 :

출력이, 서버 측 모습입니다 클래스 (즉, GreetingMaker)가 생성하는 모든 NewObj에 대한 참조를 유지하고 일종의 정리 메소드를 추가하십시오.하지만 정말 필요한가요? 이 도구를 구현하는 데 도움이되는 Pyro에서 뭔가가 누락 되었습니까? (명확성을 위해 편집)

답변

0

여기서 문제는 pyro 피클 서버 측에서 NewObj 개체 만이 NewObj 구현이 클라이언트에 알 수 없기 때문에 클라이언트 측에서 그것을 unpickle되지 않습니다.

, 그 후, 예를 new_obj.py를 들어,라는 세 번째 모듈을 작성하는 것, 문제를 해결 다음과 같이 서버와 클라이언트 모두에 가져올 수있는 한 가지 방법 :

from new_obj import NewObj 

이 드릴 것입니다 클라이언트는 NewObj 인스턴스를 unpickle 및 작업. 어쨌든, 서버에있는 객체에 대한 프록시가 아닌 클라이언트에 실제 객체 인 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() 
#... 
관련 문제