import time
import asyncio
import logging
import functools
import nest_asyncio
nest_asyncio.apply() # 需要这个,不然asyncio运行出错
from threading import Thread
logging.basicConfig( # 用日志打印输出信息
level=logging.INFO,
format="%(asctime)s %(process)d %(thread)d [*] %(message)s"
)
async def do_some_work(x):
"""
协程遇到await,事件循环将会挂起该协程,执行别的协程,直到其他的协程也挂起或者执行完毕,再进行下一个协程的执行。
"""
logging.info(f'等候:{x}秒 ')
await asyncio.sleep(x) # 模仿协程阻塞
# return '在{}秒后完成'.format(x)#1.直接用事件循环用于注册协程
logging.info('在{}秒后完成'.format(x))#2.协程需要动态的添加到事件循环中
def callback(t, future):
logging.info(f'回调函数:{t},{future.result()}')
async def main():
'''
创建协程
协程遇到await,事件循环将会挂起该协程,执行别的协程,直到其他的协程也挂起或者执行完毕,再进行下一个协程的执行。
'''
now = lambda : time.time()
start = now()
coroutine1 = do_some_work(2)# 一个协程
coroutine2 = do_some_work(3)# 一个协程
coroutine3 = do_some_work(4)# 一个协程
tasks = [# 创建多个协程任务
asyncio.ensure_future(coroutine1),# pending状态(创建时)
asyncio.ensure_future(coroutine2),
asyncio.ensure_future(coroutine3)
]
# 直接打印
dones, pendings = await asyncio.wait(tasks)# 并发 运行一个事件循环(第一种方式)
for task in dones:
logging.info(f'任务权: {task.result()}')
# results = await asyncio.gather(*tasks)# 并发 运行一个事件循环(第二种方式)
# for result in results:
# logging.info(f'任务权: {result}')
# 不在main协程函数里处理结果,直接返回await的内容
# return await asyncio.wait(tasks)# (第一种方式)
# return await asyncio.gather(*tasks)#(第二种方式)
# for task in asyncio.as_completed(tasks):# (第三种方式)
# return await task # 一个一个返回结果
logging.info(f'总花费时间:{now() - start}')
def start_loop(loop):
asyncio.set_event_loop(loop)
loop.run_forever()
def more_work(x):
logging.info('更多的工作 {}'.format(x))
time.sleep(x)
logging.info('完成更多的工作 {}'.format(x))
if __name__ == '__main__':
# 1.直接用事件循环用于注册协程-----------------------------------------------------------
# loop = asyncio.get_event_loop() # 获取时间循环
# task.add_done_callback(functools.partial(callback, 2))# 创建协程回调函数
# loop.run_until_complete(task)# 运行一个事件循环(running状态)
# loop.run_until_complete(asyncio.wait(tasks))# 并发 运行一个事件循环(第一种方式)
# loop.run_until_complete(asyncio.gather(*tasks))# 并发 运行一个事件循环(第二种方式)
# done, pending = loop.run_until_complete(main())# 协程嵌套(封装更多的io操作过程)
# for task in dones:#(第一种方式)
# logging.info(f'任务权: {task.result()}') # done状态(完成状态)
# results =loop.run_until_complete(main()) # 协程嵌套(封装更多的io操作过程)
# for result in results:#(第二种方式)
# logging.info(f'任务权: {result}')
# done = loop.run_until_complete(main())# 协程嵌套(封装更多的io操作过程)
# logging.info(f'任务权: {done}')# (第三种方式)
# try:
# loop.run_until_complete(main())
# except KeyboardInterrupt as e:
# print(asyncio.Task.all_tasks())
# print(asyncio.gather(*asyncio.Task.all_tasks()).cancel())
# loop.stop()
# loop.run_forever()
# finally:
# pass
# loop.close() # 在jupyter不能手动关闭
# 2.协程需要动态的添加到事件循环中----------------------------------------------------------
# new_loop = asyncio.new_event_loop()
# t = Thread(target=start_loop, args=(new_loop,))
# t.start()
# new_loop.call_soon_threadsafe(more_work, 6)
# new_loop.call_soon_threadsafe(more_work, 3)
asyncio.run_coroutine_threadsafe(do_some_work(6), new_loop)
asyncio.run_coroutine_threadsafe(do_some_work(4), new_loop)
输出:
2019-11-15 13:17:07,695 888 1380 [*] 等候:6秒
2019-11-15 13:17:07,695 888 1380 [*] 等候:4秒
2019-11-15 13:17:11,696 888 1380 [*] 在4秒后完成
2019-11-15 13:17:13,698 888 1380 [*] 在6秒后完成