如何在Python中的Threadpoolexecutor中运行异步函数

Ati*_*afi 2 python django asynchronous threadpoolexecutor python-asyncio

我有一个异步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')
Run Code Online (Sandbox Code Playgroud)

我得到的错误是

 RuntimeWarning: coroutine 'get_forecastweather' was never awaited
  response = wrapped_callback(request, *callback_args, **callback_kwargs)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Run Code Online (Sandbox Code Playgroud)

Pau*_*ius 5

您可以编写一个小型包装函数,在单独的线程中运行异步例程并返回结果。您可以简单地用于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
Run Code Online (Sandbox Code Playgroud)

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