【问题标题】:How to make list of twisted deferred operations truly async如何使扭曲的延迟操作列表真正异步
【发布时间】:2020-08-10 23:44:43
【问题描述】:

我是使用 Twisted 库的新手,我想制作一个异步操作列表。以下面的伪代码为例:

@defer.inlineCallbacks
def getDataAsync(host):
    data = yield AsyncHttpAPI(host) # some asyc api which returns deferred
    return data
    
@defer.inlineCallbacks
def funcPrintData():
    hosts = []; # some list of hosts, say 1000 in number
    for host in hosts:
        data = yield getDataAsync(host)
        # why doesn't the following line get printed as soon as first result is available
        # it waits for all getDataAsync to be queued before calling the callback and so print data
        print(data)

如果问题不清楚,请发表评论。有没有更好的方法来做到这一点?我应该改用 DeferredList 吗?

【问题讨论】:

    标签: python twisted twisted.internet


    【解决方案1】:

    行:

    data = yield getDataAsync(host)
    

    表示“停止运行此函数,直到 getDataAsync(host) 操作完成。如果函数停止运行,for 循环将无法进行任何后续迭代,因此这些操作甚至在第一个 @ 之后才能开始987654325@ 已完成。如果您想同时运行所有内容,则需要不要停止运行该函数,直到所有操作都已开始。例如:

    ops = []
    for host in hosts:
        ops.append(getDataAsync(host))
    

    运行后,无论是否完成,所有操作都将开始。

    您对ops 所做的操作取决于您是否希望结果与hosts 的顺序相同,或者您是否希望在它们都准备好后一次获得所有结果,或者您是否希望按顺序一次获得一个结果操作成功。

    DeferredList 用于在它们都准备好时以与输入列表相同的顺序将它们全部作为列表 (ops):

    datas = yield DeferredList(ops)
    

    如果您想在每个结果可用时对其进行处理,使用addCallback 会更容易:

    ops = []
    for host in hosts:
        ops.append(getDataAsync(host).addCallback(print))
    

    这仍然没有yield,所以整个操作组都开始了。但是,一旦该操作有结果,每个操作的回调就会运行。您仍然在ops 中留下Deferred 实例列表,如果您愿意,您仍然可以使用它来等待所有结果完成或附加整体错误处理(至少其中一个是个好主意否则,您将无法在funcPrintDat 的调用者中轻松解决悬空操作。

    【讨论】:

    • 感谢您的回答,正如我提到的主机数量以千计,我如何限制并发调用的数量,以免遇到超时/ConnectionDone 之类的问题。我想开始假设 100 个并发操作,然后如果任何一个操作完成,我想在列表中添加另一个操作,依此类推。
    猜你喜欢
    • 1970-01-01
    • 2011-05-31
    • 1970-01-01
    • 2023-03-13
    • 2011-11-08
    • 1970-01-01
    • 2014-07-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多