asyncio 学习



#
事件循环+回调(驱动生成器)+epoll(IO多路复用) #asyncio是python用于解决异步io编程的一整套解决方案 #tornado、gevent、twisted(scrapy, django channels) #torando(实现web服务器), django+flask(uwsgi, gunicorn+nginx) #tornado可以直接部署, nginx+tornado #使用asyncio # import asyncio # import time # async def get_html(url): # print("start get url") # await asyncio.sleep(2) # print("end get url") # # if __name__ == "__main__": # start_time = time.time() # loop = asyncio.get_event_loop() # tasks = [get_html("http://www.imooc.com") for i in range(10)] # loop.run_until_complete(asyncio.wait(tasks)) # print(time.time()-start_time) #获取协程的返回值 # import asyncio # import time # from functools import partial #给函数添加参数 # async def get_html(url): # print("start get url") # await asyncio.sleep(2) # return "bobby" # # def callback(url, future): # print(url) # print("send email to bobby") # # if __name__ == "__main__": # start_time = time.time() # loop = asyncio.get_event_loop() # # get_future = asyncio.ensure_future(get_html("http://www.imooc.com")) # task = loop.create_task(get_html("http://www.imooc.com")) # task.add_done_callback(partial(callback, "http://www.imooc.com")) # loop.run_until_complete(task) # print(task.result()) #wait 和 gather import asyncio import time async def get_html(url): print("start get url") await asyncio.sleep(2) print("end get url") if __name__ == "__main__": start_time = time.time() loop = asyncio.get_event_loop() tasks = [get_html("http://www.imooc.com") for i in range(10)] # loop.run_until_complete(asyncio.gather(*tasks)) # print(time.time()-start_time) #gather和wait的区别 #gather更加high-level 可以分组运行,分组取消 group1 = [get_html("http://projectsedu.com") for i in range(2)] group2 = [get_html("http://www.imooc.com") for i in range(2)] group1 = asyncio.gather(*group1) group2 = asyncio.gather(*group2) group2.cancel() loop.run_until_complete(asyncio.gather(group1, group2)) print(time.time() - start_time)

 

  • event_loop 事件循环:程序开启一个无限循环,把一些函数注册到事件循环上,当满足事件发生的时候,调用相应的协程函数

  • coroutine 协程:协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用。

  • task 任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含了任务的各种状态

  • future: 代表将来执行或没有执行的任务的结果。它和task上没有本质上的区别

  • async/await 关键字:python3.5用于定义协程的关键字,async定义一个协程,await用于挂起阻塞的异步调用接口。

 

task取消和子协程调用原理

#1. run_until_complete
# import asyncio
# loop = asyncio.get_event_loop()
# loop.run_forever()
# loop.run_until_complete()

#1. loop会被放到future中
#2. 取消future(task)

# import asyncio
# import time
#
# async def get_html(sleep_times):
#     print("waiting")
#     await asyncio.sleep(sleep_times)
#     print("done after {}s".format(sleep_times))
#
#
# if __name__ == "__main__":
#     task1 = get_html(2)
#     task2 = get_html(3)
#     task3 = get_html(3)
#
#     tasks = [task1, task2, task3]
#
#     loop = asyncio.get_event_loop()
#
#     try:
#         loop.run_until_complete(asyncio.wait(tasks))
#     except KeyboardInterrupt as e:
#         all_tasks = asyncio.Task.all_tasks()
#         for task in all_tasks:
#             print("cancel task")
#             print(task.cancel())
#         loop.stop()
#         loop.run_forever()#必须添加,否则会有异常
#     finally:
#         loop.close()

#注册协程到loop中有两种方法
#1. 通过ensure_future/create_task
#2. await

 

转载于:https://www.cnblogs.com/Erick-L/p/8932183.html

03-09
### Python `asyncio` 异步编程使用教程 #### 什么是 `asyncio` `asyncio` 是 Python 提供的一个库,专门用于编写并发代码。通过协程、任务和 Futures 这些概念来简化 I/O 密集型以及具有高延迟的操作[^2]。 #### 基本术语解释 - **协程 (Coroutine)**: 协程是一种特殊的函数,在执行过程中可以暂停并在稍后恢复。定义协程的方式是在函数前加上 `async def` 关键字。 - **事件循环 (Event Loop)**: 作为程序的核心调度器,负责管理并触发所有的异步任务。可以通过 `asyncio.get_event_loop()` 获取当前环境下的默认事件循环实例。 - **Task**: Task 对象是对 coroutine 的进一步封装,允许将其加入到 event loop 中运行,并支持取消等功能;创建方式为 `loop.create_task(coroutine)` 或者直接调用 `ensure_future()` 方法。 - **Future**: 表示一个可能还未完成的动作的结果。通常由低级别的 API 返回给高层级使用者,也可以手动创建以实现更复杂的控制逻辑。 #### 简单示例演示 下面是一个简单的例子展示如何利用 `asyncio` 实现基本的任务调度: ```python import asyncio async def say_after(delay, what): await asyncio.sleep(delay) print(what) async def main(): task1 = asyncio.create_task(say_after(1, 'hello')) task2 = asyncio.create_task(say_after(2, 'world')) # Wait until both tasks are completed (should take around 2 seconds.) await task1 await task2 # Run the async program. if __name__ == "__main__": asyncio.run(main()) ``` 这段代码展示了两个并发执行的延时打印语句,它们将在不同的时间间隔后输出文字[^1]。 #### 处理结果的方法 当涉及多个异步操作时,有时需要等待所有任务结束才能继续下一步工作,而有时候又希望能够尽早得到某个已完成任务的结果。对于前者可以直接采用 `await asyncio.gather(*tasks)` 方式收集全部返回值;而对于后者,则可借助于 `as_completed()` 函数迭代最先完成的任务列表[^3]。 例如,如果想要尽快获得任意一项任务的结果而不必等到其他都结束后再处理,那么就可以这样做: ```python import asyncio async def fetch_data(url): # Simulate network delay with sleep. await asyncio.sleep(random.randint(0, 5)) return f"data from {url}" async def get_first_result(urls): futures = [fetch_data(url) for url in urls] # Get results as they complete rather than waiting on all of them at once. for future in asyncio.as_completed(futures): result = await future break return result urls = ["http://example.com", "https://another.example.org"] print(asyncio.run(get_first_result(urls))) ``` 此段脚本会尝试访问多个 URL 并立即返回第一个成功响应的数据,而不是阻塞直到最后一个请求也完成了才给出答复。 #### 解决常见问题 针对初学者经常遇到的一些难题,这里总结了几条建议: - 如果发现某些部分并没有按照预期那样异步化,请确认是否忘记标记相应的函数为 `async` 类型或是遗漏了必要的 `await` 操作符; - 当面对大量子任务时考虑分批提交至事件循环而非一次性加载过多负载以免造成性能瓶颈; - 学习掌握异常传播机制以便更好地调试错误情况——记住即使在一个已经启动但尚未完成的任务内部抛出了未捕获异常也不会立刻终止整个应用程序流程而是会被记录下来留待后续查询; - 掌握好超时设置技巧可以在必要时候强制中断长时间无响应的任务从而避免资源浪费。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值