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 — индекс) на нем, что является общедоступным методом для получения результата.