requestloop(loopCondition) 在 loopCondition 为 False 后仍未释放

2 投票
1 回答
1872 浏览
提问于 2025-04-17 08:22

我在使用Pyro4.Daemon对象的requestLoop方法时遇到了一些问题。

我想要远程调用一个“stop()”方法,以便释放requestLoop功能并关闭我的守护进程。

这个简单的例子没有成功。

服务器代码:

#!/usr/bin/python
# -*- coding: utf-8 -*-
from daemon import Pyro4

class Audit(object):
    def start_audit(self):
        with Pyro4.Daemon() as daemon:
            self_uri = daemon.register(self)
            ns = Pyro4.locateNS()
            ns.register("Audit", self_uri)
            self.running = True
            print("starting")
            daemon.requestLoop(loopCondition=self.still_running)
            print("stopped")
            self.running = None

    def hi(self, string):
        print string

    def stop(self):
        self.running = False

    def still_running(self):
        return self.running

def main():

    # lancement de l'auditor
    auditor = Audit()
    auditor.start_audit()

if __name__ == "__main__" :
    main()

客户端代码:

import Pyro4

def main():

    with  Pyro4.Proxy("PYRONAME:Audit") as au:
        au.hi("hello")
        au.hi("another hi")
        au.stop()

我期望看到服务器打印“hello”和“another hi”,然后关闭。

但是,关闭并没有发生,服务器仍然被卡在requestloop方法里。我可以随意使用我的代理。

但是,如果我创建另一个客户端,在第一次远程调用时,服务器就会关闭,客户端会抛出一个错误:

Pyro4.errors.ConnectionClosedError: receiving: not enough data

我所有的测试都表明,我需要创建一个第二个代理,并抛出异常来让服务器的requestloop继续运行。

有没有人知道怎么解决这个问题?

1 个回答

4

如果你查看一下源代码中的 examples/callback/client.py 文件,你会看到以下注释:

# We need to set either a socket communication timeout,
# or use the select based server. Otherwise the daemon requestLoop
# will block indefinitely and is never able to evaluate the loopCondition.
Pyro4.config.COMMTIMEOUT=0.5

所以,你需要做的就是在你的服务器文件中设置 COMMTIMEOUT,根据我的测试,这样就能正常工作了。

注意:你还可以在 still_running 方法里加一个 print 语句,这样可以检查这个方法什么时候被调用。如果没有上面的配置,你会发现这个方法似乎只在接收到新事件时才会执行,因此服务器在接收到将 running 设置为 False 的事件之后,不会立即关闭。例如,如果你执行客户端程序两次,服务器就会关闭。

撰写回答