teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

ensure_futureについて追記

2021/06/21 03:26

投稿

退会済みユーザー
answer CHANGED
@@ -118,8 +118,8 @@
118
118
  async_get_data("D", 1),
119
119
  async_get_data("E", 4)
120
120
  ]
121
-
121
+ # 注)python 3.7より前のバージョンだとcreate_taskが使えません。その場合は代わりに「ensure_future」を使います。
122
- for data in asyncio.as_completed([asyncio.ensure_future(coro) for coro in coros]):
122
+ for data in asyncio.as_completed([asyncio.create_task(coro) for coro in coros]):
123
123
  res = await data
124
124
  print(res)
125
125
  return "data3 SUCCESS!"

2

変数名の修正

2021/06/21 03:26

投稿

退会済みユーザー
answer CHANGED
@@ -102,8 +102,8 @@
102
102
  @app.route("/data2")
103
103
  async def get_data2():
104
104
  # get_data1を短縮したもの。
105
- coros = [("A", 2),("B", 1),("C", 3),("D", 1),("E", 4)]
105
+ args = [("A", 2),("B", 1),("C", 3),("D", 1),("E", 4)]
106
- results = await asyncio.gather(*[async_get_data(*coro) for coro in coros])
106
+ results = await asyncio.gather(*[async_get_data(*arg) for arg in args])
107
107
  print(results)
108
108
  return "data2 SUCCESS!"
109
109
 

1

追加

2021/06/21 02:15

投稿

退会済みユーザー
answer CHANGED
@@ -58,4 +58,69 @@
58
58
 
59
59
  これは、Flask内部でイベントループが既に駆動している状態で、重ねて駆動させようとしたからです。
60
60
 
61
- get_data()コルーチンはFlaskによって自動的にイベントループに割り当てられて駆動されるため、その内部でloop.run_until_completeを呼び出すことはできません。
61
+ get_data()コルーチンはFlaskによって自動的にイベントループに割り当てられて駆動されるため、その内部でloop.run_until_completeを呼び出すことはできません。
62
+
63
+
64
+ ---
65
+ # 追記
66
+ (編集後の追加質問について)
67
+ > また、非同期処理で4秒以内にすべての処理がおわるように実装したいと思っています。
68
+
69
+ いくつかやり方があります。
70
+ 下記のコードを実行し、/data1 /data2 /data3 と異なるURLにアクセスして挙動を見てみてください。
71
+
72
+ /data1 と/data2 は同じ挙動(data2はdata1を短縮した書き方)ですが、
73
+ /data3は結果を表示するタイミングが/data1、/data2と異なります。
74
+
75
+ いずれも4秒以内に処理が完了しています。
76
+
77
+ ```
78
+ from flask import Blueprint, Flask
79
+ import asyncio
80
+ import time
81
+
82
+ app = Blueprint("app", __name__)
83
+
84
+ async def async_get_data(name, sec):
85
+ print(f"start {name}")
86
+ await asyncio.sleep(sec)
87
+ print(f"end {name}")
88
+ return f"{name}/{sec}"
89
+
90
+ @app.route("/data1")
91
+ async def get_data1():
92
+ results = await asyncio.gather(
93
+ async_get_data("A", 2),
94
+ async_get_data("B", 1),
95
+ async_get_data("C", 3),
96
+ async_get_data("D", 1),
97
+ async_get_data("E", 4)
98
+ )
99
+ print(results)
100
+ return "data1 SUCCESS!"
101
+
102
+ @app.route("/data2")
103
+ async def get_data2():
104
+ # get_data1を短縮したもの。
105
+ coros = [("A", 2),("B", 1),("C", 3),("D", 1),("E", 4)]
106
+ results = await asyncio.gather(*[async_get_data(*coro) for coro in coros])
107
+ print(results)
108
+ return "data2 SUCCESS!"
109
+
110
+
111
+ @app.route("/data3")
112
+ async def get_data3():
113
+ # コルーチンが完了するごとに結果を取得して表示。
114
+ coros = [
115
+ async_get_data("A", 2),
116
+ async_get_data("B", 1),
117
+ async_get_data("C", 3),
118
+ async_get_data("D", 1),
119
+ async_get_data("E", 4)
120
+ ]
121
+
122
+ for data in asyncio.as_completed([asyncio.ensure_future(coro) for coro in coros]):
123
+ res = await data
124
+ print(res)
125
+ return "data3 SUCCESS!"
126
+ ```