Python Twisted 和 callInThread

3 投票
2 回答
3126 浏览
提问于 2025-04-16 06:27

我把我的应用程序简化了一下,但这应该能给你一个我在做什么的例子。

def run_app(f):
    p = Popen(['/usr/bin/app'],stdout=PIPE)
    while True:
        o = p.stdout.readline()
        if o == '' and p.poll() != None: break

        reactor.callFromThread(f, o)

class Echo(Protocol):
    def connectionMade(self):

        reactor.callInThread(run_app, self.appDataReceived)

    def dataReceived(self, data):
        data = data.strip()
        if data == "getmore":
            print "getmore"

    def appDataReceived(self, u):
        print u

def main():
    factory = Factory()
    factory.protocol = Echo
    reactor.listenTCP(3646, factory)
    reactor.run()

if __name__ == "__main__":
    main()

我有一个应用程序,我想让它连接并运行一个不断向标准输出(stdout)输出数据的程序。现在我的应用程序可以正常工作,但问题是,当客户端退出套接字连接时,/usr/bin/app 仍然在继续运行。连接的套接字越多,这个程序就会越多地在运行。

有没有办法通过 Echo Procool 来结束 run_app() 这个函数的运行呢?

2 个回答

3

不要使用线程和 Popen。建议使用 Twisted 的进程支持。另外,你的 Echo 协议 需要进行分帧,否则无法保证它会收到 "getmore" 这个字符串。

1

我有几个建议,希望能帮你解决问题。

不要使用 reactor.callFromThread,应该用 deferToThread。

from twisted.internet.threads import deferToThread
deferredObj = threads.deferToThread(run_app, self.appDataReceived)

就像你在连接建立时启动线程一样,当连接断开时也需要采取行动。

示例代码:

class Echo(Protocol):
    def connectionLost(self, reason):
        print reason
        # which is crude, there should be a more elegant answer
        reactor.stop() 

确实,deferToThread 更适合处理短时间运行的任务。实际上,最好重新设计你的代码,让线程只负责运行这个过程并返回结果。

撰写回答