使用备用事件循环而不设置全局策略

jhr*_*mnn 3 python-asyncio uvloop

我使用的是uvloopwebsockets作为

import uvloop
coro = websockets.serve(handler, host, port)  # creates new server
loop = uvloop.new_event_loop()
loop.create_task(coro)
loop.run_forever()
Run Code Online (Sandbox Code Playgroud)

一切正常,我只是想知道如果不将全局asyncio政策设置为,是否可以遇到一些意想不到的问题uvloop。据我了解,只要不使用全局asyncio方法,只要不使用全局方法,就可以设置全局策略,而直接使用传递的事件循环。那是对的吗?

Vin*_*ent 5

异步中有三个主要的全局对象:

  • 策略(所有线程共有)
  • 默认循环(特定于当前线程)
  • 正在运行的循环(特定于当前线程)

在asyncio中获取当前上下文的所有尝试都通过一个函数asyncio.get_event_loop进行

要记住的一件事是,自Python 3.6(和Python 3.5.3+)以来get_event_loop它具有特定的行为:

  • 如果在循环运行时(例如在协程中)调用它,则会返回运行循环。
  • 否则,该策略将返回默认循环。

范例1:

import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
loop = asyncio.get_event_loop()
loop.run_forever()
Run Code Online (Sandbox Code Playgroud)

这里的策略是uvloop策略。返回的循环get_event_loop是uvloop,并将其设置为该线程的默认循环。运行此循环时,将其注册为运行循环。

在此示例中,get_event_loop()在此线程中的任何地方调用都会返回正确的循环。

范例2:

import uvloop
loop = uvloop.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_forever()
Run Code Online (Sandbox Code Playgroud)

在这里,该策略仍然是默认策略。返回的循环new_event_loop是uvloop,使用显式设置为该线程的默认循环asyncio.set_event_loop。运行此循环时,将其注册为运行循环。

在此示例中,get_event_loop()在此线程中的任何地方调用都会返回正确的循环。

范例3:

import uvloop
loop = uvloop.new_event_loop()
loop.run_forever()
Run Code Online (Sandbox Code Playgroud)

在这里,该策略仍然是默认策略。返回的循环new_event_loop是uvloop,但未设置为该线程的默认循环。运行此循环时,将其注册为运行循环。

在此示例中,get_event_loop()在协程内调用将返回右循环(正在运行的uvloop)。但是get_event_loop()在协程外部调用将导致新的标准asyncio循环,该循环被设置为此线程的默认循环。

因此,前两种方法很好,但不鼓励使用第三种方法。