このエラーは、コードが を 2 回呼び出しているために発生していると思いますasyncio.get_event_loop().run_until_complete(foo())
。1 回目は からfoo()
、2 回目は によって呼び出された関数 から呼び出しますfoo()
。それでは、なぜこれが問題になるのでしょうか。このループが実行されていることをなぜ気にする必要があるのでしょうか。
この質問には編集が加えられ、質問がわかりにくくなったと思います (ルールを理解せずに従うことを好む人もいるため、タイトルから「違法」な単語が削除されました)。残念ながら、これによって混乱が生じています。
エラーが発生したという事実に驚きはありません。ソースをたどってみるasyncio
と、このライブラリの作成者がこの方法で実行したかったことがわかります。そこに謎はありません。不可解なのは、ループがすでに実行されているときに、イベント ループから関数を完了まで実行するように要求するのは違法であるとライブラリの作成者が判断した理由です。
問題を 2 つの呼び出しに減らすことができ、ケース分析を通じて次の 3 つの可能性があることがわかります。
- どちらの関数も終了することはありません。
- 関数の 1 つは最終的に終了します。
- 両方の関数は最終的に終了します。
さて、3 つのケースすべてに対応できる健全な動作はあるでしょうか? 私には、ここでは複数の健全な動作が可能であることは明らかです。たとえば、
- 特別なことは何もありません。両方の関数の実行はインターリーブされ、予想どおり永久に実行され続けます。
- ループは、
run_until_complete()
2 番目の関数が完了するまで、最初のインスタンスに続くコードに制御を返しません (したがって、それ以降のコードはrun_until_complete()
実行されません)。 - 最後の関数が終了すると、ループは
run_until_complete
他のすべての呼び出しサイトを無視して、呼び出された最初のコード オブジェクトに制御を返します。
さて、この動作がすべての人に望まれるものではないことは理解できます。しかし、このライブラリはプログラマーにイベント ループの開始/停止の制御を与えることにしたので、そのような決定の結果にも対処する必要があります。同じループを複数回開始することをエラーにすると、ライブラリ コードがこれを実行できなくなるため、ライブラリの品質と有用性が低下しますasyncio
(たとえば、 の場合がまさにこれに該当しますaiohttp
)。
ベストアンサー1
nest_asyncを使用することで問題を解決しました
pip install nest-asyncio
ファイルに以下の行を追加します。
import nest_asyncio
nest_asyncio.apply()
# EDIT: the __import__ line is not needed, leaving it just
# so that the comments make sense
# __import__('IPython').embed()