我对Python Pyro4远程对象有一个问题,就好像它们是死锁一样。以下是如何重现该问题(在Windows中)。启动名称服务器:
set PYRO_HMAC_KEY=some_key
python -m Pyro4.naming
然后运行远程对象服务器:
import Pyro4
import sys
class Scheduler:
def test(self):
pass
if __name__ == '__main__':
sys.excepthook = Pyro4.util.excepthook
scheduler = Scheduler()
Pyro4.config.HMAC_KEY='some_key'
deamon = Pyro4.Daemon()
ns = Pyro4.locateNS()
ns.register("scheduler", deamon.register(scheduler))
deamon.requestLoop()
然后运行客户端:
import sys
from multiprocessing import Process
import Pyro4
class BWModule(Process):
def __init__(self):
Process.__init__(self)
self.depth = 1
def run(self):
Pyro4.config.HMAC_KEY='some_key'
self.scheduler = Pyro4.Proxy("PYRONAME:scheduler")
print "1"
sys.stdout.flush()
self.scheduler.test()
print "2"
sys.stdout.flush()
print "depth", self.depth
sys.stdout.flush()
if self.depth < 5:
for i in range(10):
newblock = self.duplicate()
newblock.depth = self.depth + 1
newblock.start()
def duplicate(self):
dup = type(self)()
return dup
if __name__ == '__main__':
sys.excepthook = Pyro4.util.excepthook
No1 = BWModule()
No1.start()
当我运行此代码时,我看到打印消息“深度X”,X从1到3但不多。我还看到在执行结束时(在没有其他事情发生之前)一堆1没有相应的2,这表明调用Pyro远程对象“self.scheduler.test()”已被阻止。这让我觉得这是Pyro的一个问题,而不是流程的问题(例如,如果可能的话,就会耗尽可用的流程)。但是,如果我将进程乘法从10减少到2(即在客户端代码中将“for i in range(10):”替换为“for i in range(2):”),执行将一直到深度5没有阻塞......
所以这是我的问题:什么是幸福的?为什么它会阻止“for i in range(10):”?对Pyro4远程对象或类似的东西是否存在可能的“客户端”进程的限制?这是一个陷入僵局的问题吗?
谢谢。
答案 0 :(得分:1)
确定。对于任何面临类似问题的人来说,这个问题似乎与可以同时保存远程对象上的引用的Pyro代理的数量有一些限制。但请注意,我只是猜测这个。这个结论是基于添加
的事实del self.scheduler
之前
if self.depth < 5:
客户端代码中的都限制了活动代理的数量并修复了问题(给它足够的时间,使用“for i in range(10):”代码上升到深度5)。
编辑:
正如我从here和某些测试中所理解的那样,THREADPOOL_MINTHREADS的值链接到远程对象的最大连接数或代理数。如果我将其设置为4,则当第五个代理尝试访问我的远程对象时,程序会冻结(就像它是死锁一样)。
还有一些可能相关的信息here。
答案 1 :(得分:0)
刚刚遇到类似的问题,更简洁的方法可能就是改变
self.scheduler = Pyro4.Proxy("PYRONAME:scheduler")
到
with Pyro4.Proxy("PYRONAME:scheduler") as self.scheduler:
# Rest of code using self.scheduler
#Rest of code not using self.scheduler
这相当于使用del self.scheduler
,除了你不需要担心放置它的位置 - python为你做了繁重的工作。