【问题标题】:Strange behaviour when trying to implement twisted deferredlist尝试实现扭曲的延迟列表时的奇怪行为
【发布时间】:2014-04-27 09:04:44
【问题描述】:

我不熟悉 twisted 并尝试构建一个简单的 POC,但是我不断收到以下错误。

running
[]
running
[]
running
[]
running
[]
running
[]
Traceback (most recent call last):
  File "./poc.py", line 23, in <module>
    dl = defer.DeferredList([tasks])
  File "/usr/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 820, in __init__
    deferred.addCallbacks(self._cbDeferred, self._cbDeferred,
AttributeError: 'list' object has no attribute 'addCallbacks'

我一直在阅读相关的扭曲文档和指南,但似乎无法弄清楚我做错了什么。有谁知道是什么导致了这个异常?

#!/usr/bin/env python
from twisted.internet import defer

def task_to_run(data):
  print 'running'
  print data

def finished(res):
  print 'finished', res

tasks = []

for x in range(0,5):
  d = defer.Deferred()      
  d.addCallback(task_to_run)
  tasks.append(d)

dl = defer.DeferredList([tasks])
dl.addCallback(finished) 

【问题讨论】:

    标签: python asynchronous twisted


    【解决方案1】:

    假设task_to_run 确实是异步运行的东西,那么@Elisha 将指向您的问题(您的示例代码列出了列表,但它不应该)。所以可运行的代码看起来像:

    #!/usr/bin/env python
    from twisted.internet import defer
    
    def task_to_run(data):
      print 'running'
      print data
    
    def finished(res):
      print 'finished', res
    
    tasks = []
    
    for x in range(0,5):
      d = defer.Deferred()      
      d.addCallback(task_to_run)
      d.callback("blah - " + str(x)) # Fire them as I make them
      tasks.append(d)
    
    dl = defer.DeferredList(tasks)
    
    dl.addCallback(finished) 
    

    输出:

    % ./deferredList.py
    running
    blah - 0
    running
    blah - 1
    running
    blah - 2
    running
    blah - 3
    running
    blah - 4
    finished [(True, None), (True, None), (True, None), (True, None), (True, None)]
    

    顺便说一句,关于 DeferredLists 的非常好的文档位于:Deferred Reference


    但如果任务实际上并没有异步运行,那么你真的可以只创建一个延迟队列:

    #!/usr/bin/env python
    from twisted.internet import defer
    
    def task_to_run(data):
      print 'running'
      print data
      return data
    
    def finished(res):
      print 'finished', res
    
    d = defer.Deferred()      
    
    for x in range(0,5):
      d.addCallback(task_to_run)
    
    d.addCallback(finished) 
    
    d.callback("blah") # Fire the deferred
    

    运行方式:

    % ./deferred.py
    running
    blah
    running
    blah
    running
    blah
    running
    blah
    running
    blah
    finished blah
    

    【讨论】:

    • 顺便说一句,我怀疑你的task_to_run 可能不是异步的原因是因为任务的任何异步输出都会在你得到的异常之后出现。如果当您运行当前代码时它显示在异常之前完成的任务,那么 DeferredList 对您没有帮助(即您在 What Deferreds don't do 陷阱中。
    【解决方案2】:

    tasks 是一个列表。然后你将它传递给另一个列表中的DeferredList。 ([tasks])
    我认为你需要换行:

    dl = defer.DeferredList([tasks])
    

    到这个:

    dl = defer.DeferredList(tasks)
    

    【讨论】:

    • 嘿,谢谢伙计,但这只是一个错字(实际上,我忍者在您发布前几分钟编辑了它)。不幸的是,问题仍然存在。
    • 您仍然传递列表列表而不是 deferred 对象列表。我已经编辑了我的答案以删除与您的错字相关的部分。
    猜你喜欢
    • 2014-07-13
    • 1970-01-01
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-08
    • 2020-11-14
    • 1970-01-01
    相关资源
    最近更新 更多