[解決済み] "Fire and forget" python async/await
質問
時々、クリティカルではない非同期処理が必要なことがありますが、それが完了するのを待ちたくはないです。 Tornado のコルーチン実装では、単に
yield
というキーワードがあります。
私は、この新しい「quot;fire & forget"」をどのように使うか考えてみました。
async
/
await
の構文がPython 3.5でリリースされました。 例:簡略化されたコードスニペット。
async def async_foo():
print("Do some stuff asynchronously here...")
def bar():
async_foo() # fire and forget "async_foo()"
bar()
しかし、何が起こるかというと
bar()
は実行されず、代わりに実行時警告が表示されます。
RuntimeWarning: coroutine 'async_foo' was never awaited
async_foo() # fire and forget "async_foo()"
解決方法は?
更新しました。
交換
asyncio.ensure_future
を
asyncio.create_task
Python >= 3.7を使用している場合は、すべての場所で、より新しい、より良い方法です。
タスクを生成する
.
asyncio.Taskでquot;fire and forget"。
のpythonドキュメントによると
asyncio.Task
に対して何らかのコルーチンを起動することが可能です。
をバックグラウンドで実行します。
. で作成したタスクは
asyncio.ensure_future
は実行をブロックしません (したがって、この関数はすぐに返されます!)。これは、あなたが要求したように、quot;fire and forget"を行う方法のように見えます。
import asyncio
async def async_foo():
print("async_foo started")
await asyncio.sleep(1)
print("async_foo done")
async def main():
asyncio.ensure_future(async_foo()) # fire and forget async_foo()
# btw, you can also create tasks inside non-async funcs
print('Do some actions 1')
await asyncio.sleep(1)
print('Do some actions 2')
await asyncio.sleep(1)
print('Do some actions 3')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
出力します。
Do some actions 1
async_foo started
Do some actions 2
async_foo done
Do some actions 3
イベントループが終了した後にタスクが実行された場合はどうなりますか?
asyncioは、イベントループが完了した瞬間にタスクが完了することを期待していることに注意してください。だから、もしあなたが
main()
に変更します。
async def main():
asyncio.ensure_future(async_foo()) # fire and forget
print('Do some actions 1')
await asyncio.sleep(0.1)
print('Do some actions 2')
プログラムが終了すると、このような警告が表示されます。
Task was destroyed but it is pending!
task: <Task pending coro=<async_foo() running at [...]
これを防ぐには、単に 保留中のタスクをすべて待機させる イベントループが終了した後に
async def main():
asyncio.ensure_future(async_foo()) # fire and forget
print('Do some actions 1')
await asyncio.sleep(0.1)
print('Do some actions 2')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
# Let's also finish all running tasks:
pending = asyncio.Task.all_tasks()
loop.run_until_complete(asyncio.gather(*pending))
タスクを待機させるのではなく、終了させる
タスクの実行を待ちたくない場合もあります(例えば、あるタスクは永遠に実行されるように作成されている場合があります)。そのような場合は、単に
cancel()
を待つ代わりに
import asyncio
from contextlib import suppress
async def echo_forever():
while True:
print("echo")
await asyncio.sleep(1)
async def main():
asyncio.ensure_future(echo_forever()) # fire and forget
print('Do some actions 1')
await asyncio.sleep(1)
print('Do some actions 2')
await asyncio.sleep(1)
print('Do some actions 3')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
# Let's also cancel all running tasks:
pending = asyncio.Task.all_tasks()
for task in pending:
task.cancel()
# Now we should await task to execute it's cancellation.
# Cancelled task raises asyncio.CancelledError that we can suppress:
with suppress(asyncio.CancelledError):
loop.run_until_complete(task)
出力します。
Do some actions 1
echo
Do some actions 2
echo
Do some actions 3
echo
関連
-
[解決済み】「RuntimeError: dictionary changed size during iteration」エラーを回避する方法とは?
-
[解決済み】NameError: 名前 'self' が定義されていません。
-
[解決済み] staticmethodとclassmethodの違いについて
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] Pythonで2つのリストを連結する方法は?
-
[解決済み] ファイルのコピー方法について教えてください。
-
[解決済み] Pythonで例外を手動で発生(スロー)させる
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】Pythonに三項条件演算子はありますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Pythonコンテナのための組み込み汎用関数操作
-
Python カメの描画コマンドとその例
-
PythonはWordの読み書きの変更操作を実装している
-
PyQt5はユーザーログインGUIインターフェースとログイン後のジャンプを実装しています。
-
Pythonコードの可読性を向上させるツール「pycodestyle」の使い方を詳しく解説します
-
任意波形を生成してtxtで保存するためのPython実装
-
[解決済み】numpyの配列連結。"ValueError:すべての入力配列は同じ次元数でなければならない"
-
[解決済み】TypeErrorを取得しました。エントリを持つ子テーブルの後に親テーブルを追加しようとすると、 __init__() missing 1 required positional argument: 'on_delete'
-
[解決済み] 'int'オブジェクトに'__getitem__'属性がない。
-
[解決済み] Pythonで可能な最も単純なasync/awaitの例