什么是事件循环:
事件循环是每个 asyncio 应用的核心。 事件循环会运行异步任务和回调,执行网络 IO 操作,以及运行子进程。
说简单点就是由于python是单线程的 程序在执行中会将所有任务放到队列中去逐一执行,当发现阻塞时就去执行其他任务,知道程序结束。
应用开发者通常应当使用高层级的 asyncio 函数,例如 asyncio.run(),应当很少有必要引用循环对象或调用其方法。
主要方法介绍:
asyncio.get_running_loop():返回当前 OS 线程中正在运行的事件循环。如果没有正在运行的事件循环则会引发 RuntimeError。 此函数只能由协程或回调来调用。
asyncio.get_event_loop():获取当前事件循环。如果当前OS线程中没有设置当前事件循环,则OS线程是主线程,并且尚未调用set_event_loop(),asyncio将创建一个新的事件循环并将其设置为当前事件循环。
由于此函数具有相当复杂的行为(特别是在使用了自定义事件循环策略的时候),更推荐在协程和回调中使用 get_running_loop() 函数而非 get_event_loop()。
应该考虑使用 asyncio.run() 函数而非使用低层级函数来手动创建和关闭事件循环。
asyncio.set_event_loop(loop):将 loop 设置为当前 OS 线程的当前事件循环。
asyncio.new_event_loop():创建一个新的事件循环。
使用事件循环创建并运行task任务
import asyncio, time
async def set_after(delay, value):
await asyncio.sleep(delay)
print(value)
async def main():
loop = asyncio.get_running_loop() # 返回当前 系统 线程中正在运行的事件循环。在这里使用它是用为 asyncio.run(main()) 已经启动了事件循环,因此get_running_loop() 可以获得
# 在事件循环中创建任务
task1 = loop.create_task(set_after(2, '... Hello'))
task2 = loop.create_task(set_after(3, '... world'))
# 执行任务
await task1
await task2
if __name__ == '__main__':
start_time = time.time()
# 方式一 直接使用高层函数run() 方法,简单粗暴,不需要自己管理太多东西
# asyncio.run(main())
# 方式二 使用底层的函数 可以更加细致的控制事件循环
loop = asyncio.get_event_loop() # 如果这里替换成get_running_loop() 则会报错,原因是当前系统中并没有在运行的事件循环。
task1 = loop.create_task(set_after(2, '... Hello'))
task2 = loop.create_task(set_after(3, '... world'))
loop.run_until_complete(asyncio.wait([task1, task2]))
print('耗时:', time.time() - start_time)
使用事件循环来使用Future对象
import asyncio, time
async def set_after(fut, delay, value):
# await asyncio.sleep(delay) # 当使用Future时 没有await 依然可以运行,但是要set_result,否则会阻塞。使用Future还可以设置返回值,实际中还是看个人应用了。
fut.set_result(value)
print(value)
async def say(delay, value):
await asyncio.sleep(delay)
print(value)
async def main():
loop = asyncio.get_running_loop() # 返回当前 系统 线程中正在运行的事件循环。
# 在事件循环中创建Futrue
fut1 = loop.create_future()
fut2 = loop.create_future()
# 为Future创建任务
task1 = loop.create_task(set_after(fut1, 2, '你好'))
task2 = loop.create_task(set_after(fut2, 3, 'Python'))
# await task1
# await task2
# 可以替换上面语句
await fut1
await fut2
print('得到返回值:', fut1.result(), fut2.result())
if __name__ == '__main__':
start_time = time.time()
# 方式一 直接使用高层函数run() 方法,简单粗暴,不需要自己管理太多东西
# asyncio.run(main())
# 方式二 使用底层的函数 可以更加细致的控制事件循环
loop = asyncio.get_event_loop() # 如果这里替换成get_running_loop() 则会报错,原因是当前系统中并没有在运行的事件循环。
future1 = asyncio.ensure_future(say(2, '... Hello'))
future2 = asyncio.ensure_future(say(3, '... world'))
# loop.run_until_complete(asyncio.wait([future1, future2]))
loop.run_until_complete(asyncio.gather(*[future1, future2])) # 可以替换上面的语句
print('耗时:', time.time() - start_time)