如果发生异常,如何停止任务LoopingCall

4 投票
1 回答
2828 浏览
提问于 2025-04-18 07:29

我刚接触Twisted,终于弄明白了deferreds是怎么工作的,但在处理任务时遇到了困难。我想做的是写一个脚本,让它循环发送REST请求,但如果在某个时刻请求失败了,我希望能停止这个循环。因为我在使用回调函数,所以很难捕捉到异常,而且我不知道怎么从错误回调中停止循环,这让我卡住了。

这是我代码的简化版本:

def send_request():
    agent = Agent(reactor)
    req_result = agent.request('GET', some_rest_link)
    req_result.addCallbacks(cp_process_request, cb_process_error)

if __name__ == "__main__":
    list_call = task.LoopingCall(send_request)
    list_call.start(2)
    reactor.run()

1 个回答

4

要结束一个 task.LoopingCall,你只需要在返回的对象上调用 stop 方法(在你的例子中是 list_call)。

你需要想办法让这个变量在你的错误处理函数(cb_process_error)中可用。可以通过把它放进一个包含 cb_process_error 的类里,或者用其他类作为伪全局变量,甚至直接使用全局变量。然后你就可以在错误处理函数里调用 list_call.stop()

顺便提一下,你说过:

因为我在使用回调,所以我不能轻易捕获异常。

这其实不太准确。错误处理函数的目的就是处理异常,这正是它被调用的原因之一!你可以看看我之前的 延迟回答,看看是否能让你对错误处理函数有更清晰的理解。

下面是一个可以运行的示例(...我并不是说这是最好的方法,只是说这是一种方法...)

#!/usr/bin/python

from twisted.internet import task
from twisted.internet import reactor
from twisted.internet.defer import Deferred
from twisted.web.client import Agent
from pprint import pprint

class LoopingStuff (object):

    def cp_process_request(self, return_obj):
        print "In callback"
        pprint (return_obj)

    def cb_process_error(self, return_obj):
        print "In Errorback"
        pprint(return_obj)
        self.loopstopper()

    def send_request(self):
        agent = Agent(reactor)
        req_result = agent.request('GET', 'http://google.com')
        req_result.addCallbacks(self.cp_process_request, self.cb_process_error)

def main():
    looping_stuff_holder = LoopingStuff()
    list_call = task.LoopingCall(looping_stuff_holder.send_request)
    looping_stuff_holder.loopstopper = list_call.stop
    list_call.start(2)
    reactor.callLater(10, reactor.stop)
    reactor.run()

if __name__ == '__main__':
  main()

假设你能访问 google.com,这个代码会在10秒内抓取页面。如果你把 agent.request 的第二个参数改成类似 http://127.0.0.1:12999 的地址(假设端口12999会拒绝连接),那么你会看到1条错误处理的输出(这也会关闭循环调用),并且会等10秒钟直到反应器关闭。

撰写回答