TypeError: объект AutoProxy не повторяется - многопроцессорная обработка

Рассмотрим следующий код сервера:

from multiprocessing.managers import BaseManager, BaseProxy

def baz(aa) :
    print "aaa"
    l = []
    for i in range(3) :
      l.append(aa)
    return l

class SolverManager(BaseManager): pass

manager = SolverManager(address=('127.0.0.1', 50000), authkey='mpm')
manager.register('solver', baz)

server = manager.get_server()
server.serve_forever()

и связанный клиент:

import sys
from multiprocessing.managers import BaseManager, BaseProxy

class SolverManager(BaseManager): pass

def main(args) :
    SolverManager.register('solver')
    m = SolverManager(address=('127.0.0.1', 50000), authkey='mpm')
    m.connect()

    for i in m.solver(args[1]):
        print i

if __name__ == '__main__':
    sys.exit(main(sys.argv))

Я думаю, что мне здесь не хватает чего-то важного. Я предполагаю, что мне нужно создать подкласс класса BaseProxy для обеспечения итеративного объекта, но до сих пор мне не удалось сделать это правильно.

когда я запускаю клиент, я получаю эту ошибку:

Traceback (most recent call last):
  File "mpmproxy.py", line 17, in <module>
    sys.exit(main(sys.argv))
  File "mpmproxy.py", line 13, in main
    for i in m.solver(args[1]):
TypeError: 'AutoProxy[solver]' object is not iterable

однако, если я попытаюсь напечатать его, список будет там... Возможно, это также как-то связано с тем, как данные сериализуются между клиентом и сервером...

в документации есть аналогичный случай (с генератором), и они используют следующий класс для доступа к данным:

class GeneratorProxy(BaseProxy):
    _exposed_ = ('next', '__next__')
    def __iter__(self):
        return self
    def next(self):
        return self._callmethod('next')
    def __next__(self):
        return self._callmethod('__next__')

я должен сделать что-то подобное? Кто-нибудь может дать мне пример и объяснить, как это работает?

Обновить

Чтобы уточнить: предположим, я добавляю класс:

class IteratorProxy(BaseProxy):
    def __iter__(self):
        print self
        return self

и в клиенте я регистрирую функцию как

SolverManager.register('solver', proxytype=IteratorProxy)

я получаю ошибку:

$python mpmproxy.py test
['test', 'test', 'test']
Traceback (most recent call last):
  File "mpmproxy.py", line 22, in <module>
    sys.exit(main(sys.argv))
  File "mpmproxy.py", line 18, in main
    for i in m.solver(args[1]):
TypeError: iter() returned non-iterator of type 'IteratorProxy'

У меня такое впечатление, что я скучаю по чему-то глупому здесь...

обновление 2

Я думаю, что я решил эту проблему:

Цель состояла в том, чтобы получить реальную стоимость:

for i in m.solver(args[1])._getvalue():
    print i

черт возьми!!! Я не уверен, что это правильный ответ или просто обходной путь...

2 ответа

Действительно, чтобы быть повторяемым, ваш класс должен определить __iter__ метод, который BaseProxy определяет, так что я думаю, наследование это правильный путь!

Хотя решение во втором обновлении OP может работать, метод _getvalue()является закрытым, и поэтому к нему не следует обращаться таким образом. Почему бы вам не попробовать вместо этого использовать тип прокси списка ( from multiprocessing.managers import ListProxy)? Хотя результат, возвращаемый с сервера, по-прежнему не будет итерируемым, насколько я видел, вы сможете запустить хорошо известную .pop()или же .pop(i)(где i — индекс) на нем, что является общедоступным методом для получения результата.

Другие вопросы по тегам