質問: time.time() print(end - start) ``` 並列化できてるか確認するのに上のようなコードをかいたのですが ```
回答: いくつかの特徴的なトピック毎に回答を書きます。 ■■■ > > 並列リクエストを送るときは必ず session を使わないといけないのでしょうか? > > ただの request ではなぜダメなんでしょうか > > > ここは`session`というよりは`aiohttp`のことですね。 いくつかの記事を見ると、`requests`はノンブロッキングではなくブロッキング動作をするとあって、それが原因でasync/awaitと組み合わせても効果が無いようです。 そして大概`aiohttp`を使いましょう、と書いてあります。 pythonで複数のhttp requestを同時に投げる方法(requests)について > > いわゆるpythonでのhttp requestのデファクトスタンダードはrequestsだと思う。ところでこのrequestsはnon blockingではないのでasyncio上で使おうとすると処理がblockしてしまう。 > > > How to run requests.get asynchronously in Python 3 using asyncio? > > `requests.get` is blocking by nature. > > You should either find async alternative for requests like `aiohttp` module: > > > How to run asynchronous web requests in parallel with Python 3.5 (without aiohttp) > > **Disclaimer:** If you have a higher version of Python available (3.5.2+), I highly recommend using aiohttp instead. It’s an incredibly robust library and a great solution for this kind of problem. > > > ■■■ `asyncio`でも`requests`は使えるけれど、それはasync/awaitではなくて`run_in_executer`とかで別スレッドとして実行するやり方のようですね。 pythonで複数のhttp requestを同時に投げる方法(requests)について > > **run_in_executor()を使う場合** > > 今度は`run_in_executor()`を使った場合を見ていく。`run_in_executor()`の第一引数にNoneを渡すとデフォルトのexecutorで呼ばれる(設定を変更していない限りconcurrent.futures.ThreadPoolExecutorで実行される)。 > > > How to run requests.get asynchronously in Python 3 using asyncio? > > or run `requests.get` in separate thread and await this thread asynchronicity using `loop.run_in_executor`: > > > > ``` > executor = ThreadPoolExecutor(2) > > async def get(url): > response = await loop.run_in_executor(executor, requests.get, url) > return response.text > > ``` > > Multithread python requests 回答に記載されている:長いので引用は省略 `asyncio`ではなく`threading.Thread()`でスレッド作成・実行している `requests`を使うにしても色々と周辺の追加ロジックが必要で、 **「使わなくても済むならもっと単純なコードに落としたいです」** は実現出来そうに無いですね。 ■■■ async/awaitはプロセスでもスレッドでも無いコルーチンというものをサポートしています。 asyncio --- 非同期 I/O コルーチンと Task 「フラットな手続き型のコードで async, await を理解できるようなサンプルはないでしょうか」という要望にはこたえられませんが、Python 3.5.4とか3.6.10のドキュメントにある図が理解しやすいかもしれません。 18.5.3.1.3. 例: コルーチンのチェーン - Python 3.6.10 ドキュメント 18.5.3.1.3. 例: コルーチンのチェーン - Python 3.5.4 ドキュメント だから「親プロセスと子プロセスがコードをどの順でどう実行されるかが全く分からないです」という疑問は、対象の名前からして理解不足でしたね。 上記の図で雰囲気程度は頭に入るのではないでしょうか。 ■■■ 「追記...これって本当に正しく並列化されてるんでしょうか」については、まあ並列化はされていないでしょうね。 ただ追記の確認プログラムをWindows10環境で実行すると、最初の2つ連続が10.30x秒、次のasync.runが5.08x秒になりました。(コメントに書いた時は連続部分はURLが1つだけ記載で5.08x~5.14x秒でした) おそらくVirtualBoxのVMで動作させていることか、その関連の設定内容に原因がありそうです。その辺の動作環境が整えば、それなりに動作してくれるでしょう。 @Fumu 7 さんのコメントとか、Pythonドキュメントに書かれたように、Pythonプログラム自身はasync/awaitでは並列動作はしていません。 しかし、正しい動作環境になれば、Webサイトへの依頼はサイトからの応答完了を待たずに複数出すことが出来るので、全体的な動きとしては並列動作しているように見せることが出来ます。 質問の最後に追記された読解内容は、おそらく合っているでしょう。 VMでかえって時間がかかってしまう件はまだ謎ですが。