簡體   English   中英

我如何使用 python 協程作為 celery 任務

[英]How can i use python coroutines as celery tasks

我的龍卷風項目中有舊的芹菜版本。 我目前的 celery 版本是 3.1.23。 有一個舊庫https://github.com/mher/tornado-celery現在已經死了,所以我想擺脫它並將 celery 更新到新版本。

我不想更改大量代碼,所以我希望能夠在我的 celery 任務中使用 async/await 語法。 有沒有可能做這樣的事情

@app.task
async def add(x, y):
    res = await some_async_function(x)
    ......

?

我只看到了同步代碼的例子,我不確定我的案例是否適合 celery

任何提示都對異步或龍卷風有好處。

升級版:

即使 celery 任務已經是異步的,我也需要使用協程的能力。 我需要協程,因為目前我們有很多使用異步調用編寫的任務,這要歸功於 tornado-celery 庫和某種黑魔法。 我們通過異步驅動程序進行數據庫調用,對 AWS 進行異步調用等等。 正因為如此,我需要有可能在 celery 任務中使用異步語法。 例如,我可以在 asyncio 中使用 event_loop.run_until_complete(...) 或在 tornado 中使用 tornado.ioloop.IOLoop.instance().run_sync(lambda: do_something(1)) 之類的東西,但這絕對不是可取的方式

據我所知,目前這是不可能的......

芹菜任務無論如何都是異步執行的,所以真的不需要使用協程。 delay()apply_async()send_task()正在返回 AsyncResult (類似未來的對象)。 這一切都是有道理的,因為 Celery 早於 Python 的 asyncio 和 async/await,后者后來進入該語言。

如果您絕對必須使用 async/await,我能想到的唯一解決方案是將異步邏輯包裝在常規 Celery 任務中。

不是最有效的解決方案,但它穩定且防白痴。

我創建了一個簡單的裝飾器,用於使用asyncio.run以同步方式運行異步函數。

def async_to_sync(func):
    @functools.wraps(func)
    def wrapped(*args, **kwargs):
        return asyncio.run(func(*args, **kwargs))

    return wrapped

如何使用它?

  1. 在某處復制裝飾器
  2. 創建你的異步函數
  3. 添加裝飾器
  4. 用常規同步功能做任何你想做的事

在此處輸入圖像描述 在此處輸入圖像描述

如果您不想使用裝飾器,則可以選擇:

@app.task()
def that_one_task():
    async def body():
        ac = AsyncClient()
        print(await ac.get('https://httpbin.org/get'))
        await ac.aclose()
        
    return asyncio.run(body())

暫無
暫無

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

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