【问题标题】:How to use async/await in Python 3.5?如何在 Python 3.5 中使用 async/await?
【发布时间】:2015-12-24 20:42:42
【问题描述】:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import time

async def foo():
  await time.sleep(1)

foo()

我无法让这个死气沉沉的简单示例运行:

RuntimeWarning: coroutine 'foo' was never awaited foo()

【问题讨论】:

  • Time.sleep 不是协程,因此即使您正确运行事件循环也无法等待。此外,如果您在事件循环中使用阻塞代码,您会再次使其同步。这样做没有意义。

标签: python python-3.x async-await coroutine python-3.5


【解决方案1】:

运行协程需要一个事件循环。使用asyncio() library 创建一个:

import asyncio

# Python 3.7+
asyncio.run(foo())

# Python 3.6 and older
loop = asyncio.get_event_loop()
loop.run_until_complete(foo())

另见Tasks and Coroutines chapter of the asyncio documentation。如果您已经运行了一个循环,您可能希望通过创建一个任务来同时运行其他协程(Python 3.7+ 中为asyncio.create_task(...),旧版本中为asyncio.ensure_future(...))。

但请注意,time.sleep() 不是一个可等待的对象。它返回None,所以你会在 1 秒后得到一个异常:

>>> asyncio.run(foo())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/.../lib/python3.7/asyncio/runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "/.../lib/python3.7/asyncio/base_events.py", line 573, in run_until_complete
    return future.result()
  File "<stdin>", line 2, in foo
TypeError: object NoneType can't be used in 'await' expression

在这种情况下,您应该改用asyncio.sleep() coroutine

async def foo():
    await asyncio.sleep(1)

它与循环配合以使其他任务能够运行。要阻止来自没有 asyncio 等效项的第三方库的代码,您可以在 executor pool 中运行该代码。请参阅 asyncio 开发指南中的 Running Blocking Code

【讨论】:

  • 如果 foo() 是一个库中的函数,是否可以封装(无需修改源代码)满足await 的要求?
  • @northtree: 你可以run blocking code in a threadpool executor 来释放异步事件循环线程。请小心阻塞无法取消它们的线程。
【解决方案2】:

如果您已经有一个循环正在运行(以及其他一些任务),您可以添加新任务:

asyncio.ensure_future(foo())

否则你可能会得到

The event loop is already running

错误。

【讨论】:

    猜你喜欢
    • 2016-02-24
    • 2017-03-04
    • 2017-02-18
    • 2019-07-20
    • 2021-10-10
    • 2019-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多