【问题标题】:uWSGI thread has existing running event loop which causes Django's SynchronousOnlyOperation exceptionuWSGI 线程存在导致 Django 的 SynchronousOnlyOperation 异常的正在运行的事件循环
【发布时间】:2021-10-27 14:28:12
【问题描述】:

我有两个 Django 视图,

def view_that_accesses_orm(request): # say end point /useorm
  user = User.objects.first()
  ...

def view_that_creates_event_loop(request): # say endpoint /createloop
  client = AsycProvider()
  ... # do stuff with client

AsyncProvider 类似于

class AsyncProvider:
  def __init__(self):
    try:
      self.__loop = asyncio.get_event_loop()
    except RuntimeError as e:
      print(e) #no running event loop
      self.__loop = asyncio.new_event_loop()
      asyncio.set_event_loop(self.__loop)
    self.__session = aiohttp.ClientSession(loop=self.__loop)

  ... # other operations with asyncio.run_until_complete, asyncio.gather, and self.__session

现在的问题是,如果我在 uWSGI 中有 1 个进程和 2 个线程。然后他们将以循环方式处理请求。

所以场景是:

  1. 用户点击/createloop(给定线程1)
  2. 用户点击/useorm(给定线程2)
  3. 用户再次点击/useorm(给定线程1)

现在在第三种情况下,有时事件循环正在运行,由于 Django 3.x 检测到正在运行的事件循环并不允许我们访问 ORM,我得到了 django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async. 异常。

我不确定事件循环如何不停止并在线程中持续存在。

请解释这究竟是什么原因以及应该如何解决?

【问题讨论】:

    标签: python django python-asyncio uwsgi


    【解决方案1】:

    问题是AsyncProvider 方法内部的某个地方正在使用asyncio.set_event_loop(self.__loop)

    所以在不同的线程中引用了相同的循环实例(没有创建新循环)。现在,由于这个循环有时也会有一些运行逻辑,而且如果在一个线程(引用了这个循环)中访问了 ORM,Django 抛出了SynchronousOnlyOperation,因为它可以检测到正在运行的事件循环。

    通过删除方法中的asyncio.set_event_loop(self.__loop)解决了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-23
      • 2017-02-18
      • 2018-07-13
      • 2014-06-10
      • 1970-01-01
      • 2022-10-17
      相关资源
      最近更新 更多