Python twisted:如何安排?

2024-04-27 02:53:03 发布

您现在位置:Python中文网/ 问答频道 /正文

在Twisted上有一天的经验,我试着安排回复tcp客户端的消息发送:

import os, sys, time
from twisted.internet import protocol, reactor

self.scenario = [(1, "Message after 1 sec!"), (4, "This after 4 secs"), (2, "End final after 2 secs")]
for timeout, data in self.scenario:
        reactor.callLater(timeout, self.sendata, data)
        print "waited %d time, sent %s\n"%(timeout, data)

现在它发送消息,但我有两个问题:
1) “timeout”从“now”开始,我想在前一个任务完成(前一条消息已发送)后计算它
2) 我不知道如何在所有邮件发送后关闭连接。如果我把self.transport.loseConnection()放在callLater之后,它会立即关闭连接。

在之前的尝试中,我没有使用reactor.callLater,而是只在for循环中使用self.transport.write()time.sleep(n)。在这种情况下,所有消息都是在所有超时之后一起发送的。。。不是我想要的。
目的是等待客户端连接、等待超时1和发送消息1、等待超时2和发送消息2。。。等最后一条消息后-关闭连接。


Tags: importself消息客户端fordatatimetimeout
2条回答

这笔交易的最终解决方案。。

import os, sys, time
from twisted.internet import protocol, reactor
import itertools

def sendScenario(self):
    def sendelayed(d):
        self.sendata(d)
        self.factory.out_dump.write(d)
        try:
            timeout, data = next(self.sc)
            reactor.callLater(timeout, sendelayed, data)
        except StopIteration:
            print "Scenario completed!"
            self.transport.loseConnection()

    self.scenario = [(1, "Message after 1 sec!"), (4, "This after 4 secs"), (2, "End final after 2 secs")]
    self.sc = iter(self.scenario)
    timeout, data = next(self.sc)
    reactor.callLater(timeout, sendelayed, data)

在使用Twisted时,需要认识到的重要一点是,没有什么可以等待任何东西。当你调用reactor.callLater()时,你要求反应器稍后调用一些东西,而不是现在。调用立即结束(在调度了调用之后,在执行它之前)。因此,您的print语句是一个谎言:您没有等待timeout时间;您根本没有等待。

你可以用多种方法修复它,使用哪种取决于你真正想要什么。如果希望第二个任务在第一个任务启动4秒后启动,只需将第一个任务的延迟(您的timeout变量)添加到第二个任务的延迟中。不过,第一个任务可能不会在您计划的时间准确开始;如果Twisted太忙而不能更早开始,它可能会在稍后开始。另外,如果你的任务需要很长时间,在第二个任务开始之前,它可能不会真正完成。

更常见的方法是第一个任务调度第二个任务,而不是立即调度第二个任务。您可以在第一个任务结束后4秒(通过在第一个任务结束时调用reactor.callLater())或在第一个任务开始后4秒(通过在第一个任务的start处调用reactor.callLater())安排它,也可以执行更复杂的计算来确定它应该何时开始,并跟踪已用时间。

当您在Twisted等待中什么都没有意识到时,在执行完所有计划任务后关闭连接就变得很容易了:您只需要调用最后一个任务self.transport.loseConnection()。对于更复杂的情况,您可能希望将Deferred链接在一起,或者使用DeferredList在所有挂起任务都已完成时执行loseConnection(),即使它们不是严格顺序的。

相关问题 更多 >