Как запустить асинхронную функцию в 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 секунды больше, поскольку рабочих потоков всего три.

Вернуться на верх