将回调添加到异步Celery任务

时间:2018-11-14 16:19:29

标签: python celery

我有一个很耗时的芹菜任务,结果很明显。我想在结果可用后立即执行本地回调(或任何回调)。

我的期望是,我可以异步调用生成数据的函数,然后在该函数返回结果时执行回调。就本演示而言,我想通过调用诸如log.info之类的琐碎函数来证明它可以工作-但在现实生活中,我可能想做一些更复杂的事情,例如将数据传递到另一个将存储结果的函数中

有一种简单的方法可以做到吗?运行脚本时,出现错误,提示我的任务无法序列化。如果我用celery任务代替了正常功能,我会得到几乎相同的错误。

stoneid_1  |   File "/usr/local/lib/python3.6/site-packages/kombu/utils/json.py", line 59, in default
stoneid_1  |     return super(JSONEncoder, self).default(o)
stoneid_1  |   File "/usr/local/lib/python3.6/json/encoder.py", line 180, in default
stoneid_1  |     o.__class__.__name__)
stoneid_1  | kombu.exceptions.EncodeError: Object of type 'log_some_information' is not JSON serializable

这是我的整个剧本:

import random
import time
import logging
import socket
from collections import namedtuple

log: logging.Logger = logging.getLogger()

from stoneid.celery.celery import app


TimeConsumingResult = namedtuple("TimeConsumingResult", ["word", "hostname"])


@app.task()
def time_consuming_thing()->TimeConsumingResult:
    delay:float = random.randrange(0,3)
    time.sleep(delay)

    items = ["zip", "zap", "zop"]
    return TimeConsumingResult(random.choice(items), socket.gethostname())


@app.task()
def log_some_information(info:TimeConsumingResult)->None:
    log.info("Message: %s, host: %s", info.word, info.hostname)


def main():
    while True:
        time.sleep(10)
        log.info("About to schedule a task:")
        time_consuming_thing.apply_async(link=log_some_information)


if __name__ == "__main__":
    logging.basicConfig()
    logging.getLogger("").setLevel(logging.INFO)
    main()

1 个答案:

答案 0 :(得分:0)

您需要使用the signature() method when adding a linksignature方法可以缩写为s。因此,在上面的代码中,使用以下代码:


df main():
    while True:
        time.sleep(10)
        log.info("About to schedule a task:")
        time_consuming_thing.apply_async(link=log_some_information.signature())