簡體   English   中英

如何在龍卷風中創建多個add_callback?

[英]How to create multiple add_callback in tornado?

我正在嘗試在龍卷風主循環中添加多個回調。 但是當我運行這段代碼時:

def task(num):
    print 'task %s' % num

if __name__ == '__main__':
    for i in range(1,5):
        tornado.ioloop.IOLoop.instance().add_callback(callback=lambda: task(num=i))
    tornado.ioloop.IOLoop.instance().start()

我得到輸出5次:'任務5',而不是任務1 ..任務5.當我改變主要時

tornado.ioloop.IOLoop.instance().add_callback(callback=lambda: task(1))
tornado.ioloop.IOLoop.instance().add_callback(callback=lambda: task(2))
tornado.ioloop.IOLoop.instance().add_callback(callback=lambda: task(3))
tornado.ioloop.IOLoop.instance().add_callback(callback=lambda: task(4))

一切正常(我在輸出中得到task1-task5)。 我在第一種情況下做錯了什么?

也許在JS中有同樣的問題? 看看這個答案: 循環內部的JavaScript閉包 - 簡單實用的例子

“問題是你的每個匿名函數中的變量i都被綁定到函數之外的同一個變量。”

嘗試簡單的測試:

def task(num):
    print 'task %s' % num

def create_task(num):
    tornado.ioloop.IOLoop.instance().add_callback(callback=lambda: task(num))

if __name__ == '__main__':
    for i in range(1,5):
        create_task(i)
    tornado.ioloop.IOLoop.instance().start()

將lambda包裝到functools.partial()函數中,該函數解決了“指針問題” IOLoop.instance().add_callback(callback=functools.partial(task, i*10))

TL;博士;

這是一個帶有“指針問題”BUG的例子:

def task(num):
    print(num)

for i in range(1, 6):
    print ("poop {0}".format(i))
    IOLoop.instance().add_callback(callback=lambda: task(i))
IOLoop.instance().start()

在上面的代碼示例中, i將是一個指向當前迭代的值range()的內存指針。 它從1變為2然后變為3,4,5。

Tornado的add_callback()異步函數將控制權返回給主程序,使得對task()函數的所有5次調用幾乎同時執行。 在這一點上, i已經獲得了5的價值。

要快速解決這個問題,請使用funtools.partial函數代替lambda並研究差異;)

這是無BUG示例:

IOLoop.instance().add_callback(callback=functools.partial(task, i*10))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM