web-dev-qa-db-ja.com

Python 3.5?でasync / awaitを使用するには?

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import time

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

foo()

私はこの死んだ単純な例を実行することができませんでした:

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

コルーチンを実行するには、イベントループが必要です。 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())
_

asyncioドキュメントの Tasks and Coroutinesの章 も参照してください。既にループを実行している場合は、タスクを作成して追加のコルーチンを同時に実行する必要があります(asyncio.create_task(...) in Python 3.7+、asyncio.ensure_future(...)古いバージョンで)。

ただし、time.sleep()not待機可能なオブジェクトではないことに注意してください。 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 を参照してください。

73
Martijn Pieters

ループを既に実行している場合(他のいくつかのタスクを使用)、次を使用して新しいタスクを追加できます。

asyncio.ensure_future(foo())

そうでなければ、あなたは得るかもしれません

The event loop is already running

エラー。

2
lenooh