【问题标题】:Querying Django ORM inside celery task: SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async在 celery 任务中查询 Django ORM:SynchronousOnlyOperation:您不能从异步上下文中调用它 - 使用线程或 sync_to_async
【发布时间】:2021-12-23 03:55:19
【问题描述】:

我们在 Django 旁边使用 celery 作业,在不同的 celery 任务中,有好几次 celery 任务通过 Django 的 ORM 读取和写入数据库。

每隔一段时间在 celery 任务中使用 ORM 时,任务会抛出:

SynchronousOnlyOperation:您不能从异步上下文中调用它 - 使用线程或 sync_to_async。

我觉得奇怪的是它有时会发生,而不是每次通过 ORM 进行查询时?其次,当尝试按照此处 Django 文档中的建议解决它时:

https://docs.djangoproject.com/en/3.2/topics/async/

像这样:Example of sync_to_asynch ussage

我遇到了另一个问题: TypeError: 'coroutine' object is not iterable

我的问题是:

  1. 为什么这个问题只是偶尔出现,而不是每次我在 celery 任务中使用 ORM 查询时都会出现?

  2. 有办法解决吗?

环境

celery 任务使用 gevent 运行,如下所示: celery -A 任务工作者 -P gevent -c 10 -l INFO -E

Python 3.8

Django 3.1.4

芹菜 5.1.0

【问题讨论】:

  • 如果您需要传递与数据库相关的数据,请确保不要通过 args 传递模型等对象,只需传递 pk 然后在函数中进行查询,因为 celery 没有使用作为参数传递的 ORM 对象可以正常工作。
  • 谢谢!不过,这已经处理过了,在这种情况下不是问题。
  • 请在您的问题中直接包含相关代码以及完整的回溯。

标签: python django celery django-orm gevent


【解决方案1】:

sync_to_async() 将返回一个协程。正如 TypeError 所暗示的,您不能直接迭代协程。你必须await它,如示例所示。

来自文档:

from asgiref.sync import sync_to_async

results = await sync_to_async(Blog.objects.get, thread_sensitive=True)(pk=123)

在你的图片中,你没有await这个电话。

【讨论】:

  • 谢谢!这是完全正确的。如果我等待调用,我遇到的下一个问题是它要求函数声明是异步的。我认为当时的问题是 Celery gevent 正在产生绿色线程(因为我使用 gevent),它并不是一个可以用 async 关键字声明的异步上下文,因为 celery 正在处理这个线程异步绿色线程的产生。有什么办法可以解决这个问题,还是我必须在我的 celery 设置中使用 prefork 而不是 gevent?
猜你喜欢
  • 2020-09-07
  • 2022-11-27
  • 2023-03-03
  • 2020-05-08
  • 2016-09-23
  • 2016-12-13
  • 1970-01-01
  • 2015-11-14
  • 2019-07-02
相关资源
最近更新 更多