asyncio future 和 concurrent.futures 区别

asyncio future 和 concurrent.futures

asyncio future 是协程实现的异步方式, concurrent.futures 是通过线程池或进程池实现的异步
两个future 是不一样的, 但是,asyncio 可以将 concurrent.futures 线程池或进程池实现的异步转换为
协程方式的异步, 用await 的方式 等待 concurrent.futures 调用结束, 这种一般适应于 未支持异步协程库的方法调用上,

异步任务中需要异步io操作,但是 没有对应的异步io库,比如mysql数据库连接啊, 可以通过concurrent.futures 创建线程池调用同步的mysql 模块,然后通过async.run_in_executor() 方法将线程池或进程池异步转 async await 方式
如:

	from concurrent.futures import ThreadPoolExecutor
	from concurrent.futures import ProcessPoolExecutor

	import asyncio

	import requests


	def get_baidu(i):
	    print("aaa")
	    requests.get("https://www.baidu.com")
	    print("请求结束", i)
	    return i


	async def main():
		# 获取当前事件循环
	    loop = asyncio.get_running_loop()

	    # 进程池异步:
	    # with ProcessPoolExecutor(max_workers=2) as executor:

	    # 开启线程池异步
	    with ThreadPoolExecutor(max_workers=2) as executor:
	    	# 将线程同步对象转为 异步方式调用, 如果不转的,直接 executor.submit(get_baidu, 1)  的话,
	    	# 这个协程是不会等待的,直接就往下走了,不会接收到 get_baidu 方法的返回值, 所有先将 concurrent.futures 线程池
	    	# 异步线程转为协程方式调用,然后await 等待结果
	        res1 = await loop.run_in_executor(executor, get_baidu, 1)
	        res2 = await loop.run_in_executor(executor, get_baidu, 2)
	        print(res1)
	        print(res2)
	    print("end ")


	loop = asyncio.get_event_loop()
	loop.create_task(main())
	loop.create_task(print_hello())
	loop.run_forever()

上面这个协程看起来是同步的,get_baidu 方法中 print("aaa") 是顺序打印, 因为在 main 协程中 先 res1 = await loop.run_in_executor(executor, get_baidu, 1) 这个协程
执行这个协程的时候 尽管让出了cpu执行权,但是 res2 = await loop.run_in_executor(executor, get_baidu, 2)  在堵塞之后, 执行 res1 的时候 loop 事件循环中
是没有其他异步任务的,使用看起来就像同步,这时候可以添加一个新的协程测试

	import asyncio
	from concurrent.futures import ThreadPoolExecutor
	from concurrent.futures import ProcessPoolExecutor

	import requests


	async def print_hello():
	    print("hhhhhhhhh")


	def get_baidu(i):
	    print("aaa")
	    requests.get("https://www.baidu.com")
	    print("请求结束", i)
	    return i


	async def main():
	    loop = asyncio.get_running_loop()
	    
	    # 进程池
	    # 	with ProcessPoolExecutor(max_workers=2) as executor:        

	    with ThreadPoolExecutor(max_workers=2) as executor:        
	        res1 = await loop.run_in_executor(executor, get_baidu, 1)
	        res2 = await loop.run_in_executor(executor, get_baidu, 2)
	        print(res1)
	        print(res2)
	    print("end ")


	if __name__ == '__main__':

		loop = asyncio.get_event_loop()
		loop.create_task(main())
		# 往事件循环中添加一个新的协程任务测试
		loop.create_task(print_hello())
		loop.run_forever()


	```
	运行这个可以看到 当第一个 await 调用打印 aaa 后立刻就执行了 print_hello  协程中的 print("hhhhhhhhh")
posted @ 2021-07-22 15:15  tnan  阅读(449)  评论(0)    收藏  举报