通过任务执行数据库查询时,celery 出现 django 错误:在线程中创建的 DatabaseWrapper 对象只能在同一线程中使用

whi*_*hat 5 django redis celery python-3.x

堆:

姜戈3.0.2
蟒蛇3.8.1
芹菜4.4.0
雷迪斯3.2.0

启动芹菜的命令:celery -A app_project worker -l info

我用来celery在我的项目中运行后台任务django。在开发机器上它运行完美,没有任何错误。开发和生产都在同一个堆栈上运行;我已经手动检查并匹配它们。然而,我仍然面临这个问题。

问题:Celery 在尝试对数据库进行查询时抛出以下错误。

Traceback (most recent call last):
  File "/webapps/app/.virtualenvs/base38/local/lib/python3.8/site-packages/celery/app/trace.py", line 385, in trace_task
    R = retval = fun(*args, **kwargs)
  File "/webapps/app/.virtualenvs/base38/local/lib/python3.8/site-packages/celery/app/trace.py", line 650, in __protected_call__
    return self.run(*args, **kwargs)
  File "/webapps/app/backend/app/tasks.py", line 22, in task_assign_photo_to_dish
    if dishq.exists():
  File "/webapps/app/.virtualenvs/base38/local/lib/python3.8/site-packages/django/db/models/query.py", line 777, in exists
    return self.query.has_results(using=self.db)
  File "/webapps/app/.virtualenvs/base38/local/lib/python3.8/site-packages/django/db/models/sql/query.py", line 537, in has_results
    return compiler.has_results()
  File "/webapps/app/.virtualenvs/base38/local/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1114, in has_results
    return bool(self.execute_sql(SINGLE))
  File "/webapps/app/.virtualenvs/base38/local/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1142, in execute_sql
    cursor = self.connection.cursor()
  File "/webapps/app/.virtualenvs/base38/local/lib/python3.8/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/webapps/app/.virtualenvs/base38/local/lib/python3.8/site-packages/django/db/backends/base/base.py", line 260, in cursor
    return self._cursor()
  File "/webapps/app/.virtualenvs/base38/local/lib/python3.8/site-packages/django/db/backends/base/base.py", line 238, in _cursor
    return self._prepare_cursor(self.create_cursor(name))
  File "/webapps/app/.virtualenvs/base38/local/lib/python3.8/site-packages/django/db/backends/base/base.py", line 228, in _prepare_cursor
    self.validate_thread_sharing()
  File "/webapps/app/.virtualenvs/base38/local/lib/python3.8/site-packages/django/db/backends/base/base.py", line 553, in validate_thread_sharing
    raise DatabaseError(
django.db.utils.DatabaseError: DatabaseWrapper objects created in a thread can only be used in that same thread. The object with alias 'default' was created in thread id 139987604641728 and this is thread id 139987115662208.
[2020-02-05 23:04:51,621: ERROR/MainProcess] Signal handler <bound method DjangoWorkerFixup.on_task_postrun of <celery.fixups.django.DjangoWorkerFixup object at 0x7f515c6ebd30>> raised: DatabaseError("DatabaseWrapper objects created in a thread can only be used in that same thread. The object with alias 'default' was created in thread id 139987604641728 and this is thread id 139987115662208.")
Run Code Online (Sandbox Code Playgroud)

更新

@shared_task()
def task_assign_photo_to_dish(id):
    dishq = Dish.objects.filter(pk=id)
    if dishq.exists():
        dish = dishq[0]
        DishFile.objects.filter(dish=dish).delete()
        pq  = Post.objects.filter(dish=dish).annotate(c=Count('liked_by')).order_by('-c')
        for p in pq[:5]:
            instance = DishFile.objects.create(dish=dish, file=p.post_files.all().order_by('?')[0].file)
    return "Done"
Run Code Online (Sandbox Code Playgroud)

the*_*ORN -1

你是在 Windows 上吗?

我遇到了同样的问题,但是一旦我部署到heroku(在Linux上运行),它就工作了。