如何 运行 Threadpoolexecutor 中的异步函数 python

how to run async function in Threadpoolexecutor in python

我有一个异步 get_forecastweather 函数给我 JSON 天气数据,我知道我们不能在同步中执行异步函数,但我如何在单独的线程中执行此操作,需要帮​​助,在此先感谢

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

您可以编写一个小的包装函数,运行在单独的线程中作为您的异步例程,并 return作为结果。为此,您可以简单地使用 asyncio.run。 ThreadPoolExecutor 机制将为您创建新的线程,asyncio.run 方法将创建一个新的事件循环,运行 它,return 结果然后关闭循环。这是一个示例程序,我生成一个介于两个限制之间的随机整数,而不是您对天气的请求:

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

我加入了时间戳以显示时间延迟,并证明三个线程 运行ning 是并行的。对包装器的前三个调用在 3 秒内完成,但第四个需要 3 秒以上,因为只有三个工作线程。