Python扭曲:如何调度?

发布于 2024-09-11 00:14:53 字数 822 浏览 1 评论 0原文

在 Twisted 中有 1 天的经验,我尝试安排消息发送以回复 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)

现在它发送消息,但我有 2 个问题:
1)“超时”是从“现在”开始的,我想在之前的每个任务完成后(发送之前的消息)进行计数
2)我不知道如何在发送所有消息后关闭连接。如果我将 self.transport.loseConnection() 放在 callLater 之后,它会立即关闭连接。

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

Having 1-day experience in Twisted I try to schedule message sending in reply to tcp client:

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)

Now it sends messages, but I have 2 problems:
1) "timeout" is going from "now", and I want to count it after each previous task was completed (previous message was sent)
2) I don't know how to close connection after all messages were sent. If I place self.transport.loseConnection() after callLaters it closes connection immediately.

In previous try I didn't use reactor.callLater, but only self.transport.write() and time.sleep(n) in for loop. In this case all messages were sent together after all timeouts passed... Not something I wanted.
The purpose is to wait for client connection, wait timeout1 and send message1, wait timeout2 and send message2, ... etc. After final message - close connection.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蓝梦月影 2024-09-18 00:14:53

使用 Twisted 时要认识到的重要一点是,没有什么会等待。当您调用reactor.callLater()时,您是在要求反应器稍后调用某些内容,而不是现在。调用立即完成(在安排调用之后,在执行调用之前)。因此,您的 print 语句是一个谎言:您没有等待 超时时间;你根本就没有等。

您可以通过多种方式修复它,使用哪种方式取决于您的实际需要。如果您希望第二个任务在第一个任务启动后四秒启动,您只需将第一个任务的延迟(您的超时变量)添加到第二个任务的延迟中即可。第二个任务。不过,第一个任务可能不会在您安排的时间准确开始;如果 Twisted 太忙而无法早点开始,则可能会稍后开始。此外,如果您的任务需要很长时间,则在第二个任务开始之前实际上可能尚未完成。

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

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

The important thing to realize when working with Twisted is that nothing waits for anything. When you call reactor.callLater(), you're asking the reactor to call something later, not now. The call finishes right away (after the call has been scheduled, before it has been executed.) Consequently, your print statement is a lie: you didn't wait timeout time; you didn't wait at all.

You can fix it in multiple ways, and which to use depends on what you actually want. If you want the second task to start four seconds after the first task started, you can simply add the delay (your timeout variable) of the first task to the delay of the second task. The first task may not start exactly when you schedule it, though; it may start later, if Twisted is too busy to start it sooner. Also, if your task takes a long time it may not actually be done before the second task starts.

The more common way is for the first task to schedule the second task, instead of scheduling the second task right away. You can schedule it four seconds after the first task ended (by calling reactor.callLater() at the end of the first task), or four seconds after the first task started (by calling reactor.callLater() at the start of the first task), or perform more complex calculations to determine when it should start, keeping track of elapsed time.

When you realize nothing in Twisted waits, dealing with closing the connection when you've performed all scheduled tasks becomes easy: you simply have your last task call self.transport.loseConnection(). For more complex situations you may want to chain Deferreds together, or use a DeferredList to perform the loseConnection() when all pending tasks have finished, even when they aren't strictly sequential.

秋千易 2024-09-18 00:14:53

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

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)

Final solution for this deal..

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文