質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
並列処理

複数の計算が同時に実行される手法

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1166閲覧

pythonの非同期処理

maeta

総合スコア12

並列処理

複数の計算が同時に実行される手法

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/09/13 07:34

編集2020/09/13 08:39

非同期に処理を実行したい

APIの処理で、DBに書き込む処理の後、通知を出したいが
通知の処理が完了する前にAPIの呼び出し側にレスポンスを返したい。

サンプルを作成して実行しているが非同期にならなくて困っている。

最初に試したもの

test.py

python

1import asyncio 2import requests 3 4url = 'https://google.co.jp' 5 6 7def ex(): 8 print(" 5 ") 9 r = requests.get(url) 10 print(r.status_code) 11 print(" 6 ") 12 13 14loop = asyncio.get_event_loop() 15print(" 1 ") 16loop.run_in_executor(None, ex) 17print(" 2 ")

これだと以下の結果になりうまくいく
1
5
2
200
6

APIで試した

api.py

python

1import asyncio 2from django.utils.timezone import localtime 3from hr.common import glgl as glgl 4 5 6class testAPI(ViewSet): 7 8 @action(detail=False, methods=['post']) 9 def test(self, request): 10 print("■■■ T1 ■■■ : " + str(localtime())) 11 loop = asyncio.new_event_loop() 12 asyncio.set_event_loop(loop) 13 loop.run_in_executor(None, glgl.glgl()) 14 loop.close() 15 16 print("■■■ T2 ■■■ : " + str(localtime())) 17 return Response("A", status=status.HTTP_200_OK)

glgl.py

python

1import requests 2from django.utils.timezone import localtime 3 4 5def glgl(): 6 7 print("■■■ G1 ■■■ : " + str(localtime())) 8 r = requests.get('https://google.co.jp') 9 print(r) 10 print("■■■ G2 ■■■ : " + str(localtime()))

これだと上手くいかない
■■■ T1 ■■■ : 2020-09-13 16:30:38.730048+09:00
■■■ G1 ■■■ : 2020-09-13 16:30:38.730943+09:00
<Response [200]>
■■■ G2 ■■■ : 2020-09-13 16:30:39.237304+09:00
■■■ T2 ■■■ : 2020-09-13 16:30:39.239700+09:00

######以下の結果になるように非同期処理をするにはどうすればいいのでしょうか?
■■■ T1 ■■■ : 2020-09-13 16:30:38.730048+09:00
■■■ G1 ■■■ : 2020-09-13 16:30:38.730943+09:00
■■■ T2 ■■■ : 2020-09-13 16:30:38.730943+09:00
<Response [200]>
■■■ G2 ■■■ : 2020-09-13 16:30:39.237304+09:00

###追記
色々検索した結果
aiohttpを調べてみようと思います。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

diff

1+ loop.run_in_executor(None, glgl.glgl) 2- loop.run_in_executor(None, glgl.glgl()) 3- loop.close()

問題点: glgl.glgl() を呼び出してから
その戻り値を引き数として loop.run_in_executorへ渡しています。

また、loop.close() で run_in_executor の完了を待つことなく
asyncio の非同期ループを中断してるので、RuntimeError となります。

修正方法:
run_in_executor へ glgl.glgl オブジェクトを渡すように、括弧を外してください。

loop.close() に関しては、そのまま外しても良いのですが、
(丁寧に後始末するなら、run_in_executorの戻り値のFutureに add_done_callback(loop.close) とglglの実行が終わってから呼び出す)
このケースでは asyncio を使う恩恵があまり見られないので、
concurrent.futures.Executor で済んだりします。

asyncioを使う場合は、
非同期に対応したaiohttp ライブラリを検討して見て下さい。

投稿2020/09/13 08:57

編集2020/09/13 09:08
teamikl

総合スコア8760

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maeta

2020/09/13 08:59

回答ありがとうございます。 早速試してみます。
maeta

2020/09/13 09:10

修正して試してみました。 修正方法に書いていただいた通り glgl.glglのカッコをとって loop.close()も消したところ 以下の結果になりました。 ■■■ T1 ■■■ : 2020-09-13 18:06:53.667902+09:00 ■■■ G1 ■■■ : 2020-09-13 18:06:53.760619+09:00 ■■■ T2 ■■■ : 2020-09-13 18:06:53.761718+09:00 <Response [200]> ■■■ G2 ■■■ : 2020-09-13 18:06:54.205422+09:00 ありがとうございます。
maeta

2020/09/13 09:16

教えていただいた、 concurrent.futures.Executor aiohttp も、引き続き調査していきます。 第一歩の非同期処理が実施できたので、これを実装して レスポンスがどうなるか試していきます。 とても助かりました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問