如何在Python的ThreadPoolExecutor中运行异步函数?异步天气接口调用报错求助
解决同步代码中在独立线程执行异步函数的问题
我明白你遇到的困扰了——你想用ThreadPoolExecutor在独立线程里运行异步函数,但线程池只会把异步函数当作普通函数执行,返回的是未被调度执行的协程对象,这就是为什么会弹出coroutine was never awaited的警告。要搞定这个问题,我们需要在子线程里手动启动异步事件循环,驱动协程完成执行。
下面是具体的修复方案:
步骤1:编写异步协程的包装函数
先写一个包装器,它会在子线程中创建并运行异步事件循环,专门用来执行你的get_forecastweather协程:
import asyncio import concurrent.futures def run_async_coroutine(coroutine_func, *args, **kwargs): # 在子线程中创建新的事件循环 loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) try: # 运行协程直到完成,返回执行结果 return loop.run_until_complete(coroutine_func(*args, **kwargs)) finally: # 关闭事件循环,避免资源泄漏 loop.close()
步骤2:修改视图代码
把包装函数提交给线程池,而不是直接提交你的异步函数:
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: # 提交包装器,传入异步函数和它的参数 future = executor.submit(run_async_coroutine, get_forecastweather, city_name, key) result = future.result() print('Result from thread: ', result) return render(request,'weather/weather_detail.html')
为什么原来的代码会出错?
当你直接把异步函数get_forecastweather提交给线程池时,线程池只是调用了这个函数,得到的是一个coroutine对象,而不是执行后的结果。协程必须在异步事件循环中被调度才能运行,线程池本身不会处理协程的调度逻辑,所以我们需要手动在子线程里启动事件循环来驱动它。
额外优化方案:使用Django原生异步视图(如果适用)
如果你的Django版本是3.1及以上,其实可以直接把视图定义为异步函数,Django会自动处理事件循环的运行,代码会更简洁:
async def weather_detail(request): if request.method == 'GET': city_name = 'my_city' key = 'mykey' result = await get_forecastweather(city_name, key) print('Result: ', result) return render(request,'weather/weather_detail.html')
注意:使用异步视图时,要确保你的Django项目支持异步运行(比如用ASGI服务器部署,WSGI模式下也能兼容,但会用线程处理异步视图)。
内容的提问来源于stack exchange,提问作者Atif Shafi
相关产品推荐
相关产品推荐

