类型错误: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 个回答
0
虽然OP在第二次更新中提到的解决方案可能有效,但方法 _getvalue()
是私有的,所以不应该这样访问。你可以试试使用列表代理类型(from multiprocessing.managers import ListProxy
)。虽然从服务器返回的结果仍然不能被迭代,但据我所知,你应该能够使用大家都熟悉的 .pop()
或 .pop(i)
(其中 i 是索引)来操作它,这些都是结果的公开方法。
0
没错,要让你的类可以被遍历,你需要定义一个叫做 __iter__
的方法,这个方法是 BaseProxy
里定义的。所以,我觉得继承是个不错的选择!