Как запустить асинхронную функцию в Threadpoolexecutor в python
У меня есть async get_forecastweather функция, которая дает мне JSON данные о погоде, я понимаю, что мы не можем выполнить async функцию внутри sync, но как мне сделать это внутри отдельного потока, нужна помощь, заранее спасибо
def weather_detail(request):
if request.method == 'GET':
city_name = 'my_city'
key = 'mykey'
result = None
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
response = executor.submit(get_forecastweather,city_name,key)
result = response.result()
print('Result from thread ',result)
return render(request,'weather/weather_detail.html')
ошибка, которую я получаю
RuntimeWarning: coroutine 'get_forecastweather' was never awaited
response = wrapped_callback(request, *callback_args, **callback_kwargs)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Вы можете написать небольшую функцию-обертку, которая выполняет вашу асинхронную процедуру в отдельном потоке и возвращает результат. Для этого вы можете просто использовать asyncio.run
. Механизм ThreadPoolExecutor создаст для вас новые потоки, а метод asyncio.run
создаст новый цикл событий, выполнит его, вернет результат и затем закроет цикл. Вот пример программы, где вместо вашего запроса о погоде я генерирую случайное целое число между двумя пределами:
from concurrent.futures import ThreadPoolExecutor
import random
import time
import asyncio
# You would use weather_detail here
async def get_random(n0, n1):
await asyncio.sleep(3.0)
return random.randint(n0, n1)
def wrapper(coro):
return asyncio.run(coro)
def main():
print("Start", time.ctime())
with ThreadPoolExecutor(max_workers=3) as executor:
arglist = ((10, 20), (30, 40), (50, 60), (90, 100))
coros = [get_random(n0, n1) for n0, n1 in arglist]
for r in executor.map(wrapper, coros):
print(r, time.ctime())
main()
# Output:
# Start Fri Sep 10 00:45:13 2021
# 15 Fri Sep 10 00:45:16 2021
# 40 Fri Sep 10 00:45:16 2021
# 52 Fri Sep 10 00:45:16 2021
# 99 Fri Sep 10 00:45:19 2021
Я включил метки времени, чтобы показать временные задержки и доказать, что три потока работают параллельно. Первые три вызова обертки завершаются за 3 секунды, но четвертый занимает на 3 секунды больше, поскольку рабочих потоков всего три.