Как использовать объект прокси Pyro как фабрику? - PullRequest
3 голосов
/ 11 марта 2012

Я хочу использовать Pyro с существующим набором классов, которые включают шаблон фабрики, то есть объект класса A (как правило, будет только один из них) используется для создания экземпляров объектов класса B (может быть произвольныйчисло из них) через заводской метод.Итак, я выставляю объект класса А. как прокси-объект Pyro.

Я расширил вводный пример кода Pyro , чтобы примерно отразить то, что я пытаюсь сделать.Код на стороне сервера выглядит следующим образом:

# 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:foo@10.2.129.6: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:foo@10.2.129.6: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, который может помочь мне реализовать это?

(отредактировано для ясности)

Ответы [ 2 ]

1 голос
/ 01 декабря 2015

Я недавно сталкивался с этой функцией и использую ее.Это важно для моего кода, который использует аналогичный шаблон фабрики.

Pyro Server

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()
#...
0 голосов
/ 11 марта 2012

Проблема здесь в том, что pyro выбирает объект NewObj на стороне сервера, но не может его удалить на стороне клиента, поскольку реализация NewObj неизвестна для клиента.

Один из способов решения этой проблемы - создать третий модуль, например, new_obj.py, а затем импортировать его как на сервер, так и на клиент, следующим образом:

from new_obj import NewObj

Это позволитклиент распакует экземпляр NewObj и будет работать с ним.В любом случае, обратите внимание, что это будет настоящий NewObj объект, живущий на клиенте, а не прокси для объекта, живущего на сервере.

...