20 | 揭秘 Python 协程
该思维导图由 AI 生成,仅供参考
- 深入了解
- 翻译
- 解释
- 总结
Python协程:并发编程的新利器 Python协程是一种强大的并发编程方式,通过async修饰词声明异步函数,以及使用await来调用协程实现异步执行。本文深入浅出地介绍了Python中协程的使用方法,从协程的背景和发展出发,引出了协程的重要性。通过一个简单的爬虫例子展示了使用协程进行并发化的优势。在Python 3.7以上版本中,使用协程编写异步程序变得非常简单。通过对比多线程的写法,展示了协程的清晰性和高效性。此外,文章还详细介绍了协程任务的创建、运行和取消,以及如何处理协程任务的超时和错误。最后,通过实例展示了使用协程实现生产者消费者模型和一个完整的协程爬虫。总之,本文通过实例详细介绍了Python中协程的基本概念和使用方法,适合读者快速了解和掌握协程的特点和使用技巧。 文章还提到了协程和多线程的区别,以及协程的写法更加简洁清晰,对于中小级别的并发需求已经毫无压力。最后,留下了一个思考题,即协程如何实现回调函数,鼓励读者留言讨论并分享文章。整体而言,本文是一篇介绍Python协程的实用指南,为读者提供了深入了解并发编程的机会。
《Python 核心技术与实战》,新⼈⾸单¥59
全部留言(123)
- 最新
- 精选
- Jingxiao置顶思考题答案: 在 python 3.7 及以上的版本中,我们对 task 对象调用 add_done_callback() 函数,即可绑定特定回调函数。回调函数接受一个 future 对象,可以通过 future.result() 来获取协程函数的返回值。 示例如下: import asyncio async def crawl_page(url): print('crawling {}'.format(url)) sleep_time = int(url.split('_')[-1]) await asyncio.sleep(sleep_time) return 'OK {}'.format(url) async def main(urls): tasks = [asyncio.create_task(crawl_page(url)) for url in urls] for task in tasks: task.add_done_callback(lambda future: print('result: ', future.result())) await asyncio.gather(*tasks) %time asyncio.run(main(['url_1', 'url_2', 'url_3', 'url_4'])) 输出: crawling url_1 crawling url_2 crawling url_3 crawling url_4 result: OK url_1 result: OK url_2 result: OK url_3 result: OK url_4 Wall time: 4 s2019-07-0142
- Jingxiao置顶发现评论区好多朋友说无法运行,在这里统一解释下: 1. %time 是 jupyter notebook 自带的语法糖,用来统计一行命令的运行时间;如果你的运行时是纯粹的命令行 python,或者 pycharm,那么请把 %time 删掉,自己用传统的时间戳方法来记录时间也可以;或者使用 jupyter notebook 2. 我的本地解释器是 Anaconda Python 3.7.3,亲测 windows / ubuntu 均可正常运行,如无法执行可以试试 pip install nest-asyncio,依然无法解决请尝试安装 Anaconda Python 3. 这次代码因为使用了较新的 API,所以需要较新的版本号,但是朋友们依然出现了一些运行时问题,这里先表示下歉意;同时也想说明的是,在提问之前自己经过充分搜索,尝试后解决问题,带来的快感,和能力的提升,相应也是很大的,一门工程最需要的是 hands on dirty work(动手做脏活),才能让自己的能力得到本质的提升,加油!2019-06-251076
- Airnm.毁豆瓣那个发现requests.get(url).content/text返回都为空,然后打了下status_code发现是418,网上找418的解释,一般是网站反爬虫基础机制,需要加请求头模仿浏览器就可跳过,改为下面的样子就可通过:url = "https://movie.douban.com/cinema/later/beijing/" head={ 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36', 'Referer':'https://time.geekbang.org/column/article/101855', 'Connection':'keep-alive'} res = requests.get(url,headers=head)
作者回复: 👍,可能是增加了反爬虫机制
2020-04-1838 - jackstraw有点没明白,前面说任务创建后立马就开始执行了么?怎么后面在解密底层运行过程的时候,说任务创建后等待执行?到底是哪一个呀?
作者回复: 原文是“任务创建后很快就会被调度执行”,并不是“立马就开始执行”;其次在解密底层运行时,main 函数也可以理解为一个正常的 task,要等这个 task 进入 await 的状态,才会调度下一个 task
2020-01-143 - 长期规划老师,在最后那个协程例子中为何没用requests库呢?是因为它不支持协程吗
作者回复: 协程使用的是 aiohttp 并发网络 io 库,因此就不需要 requests 了
2019-12-202 - 一凡协程是单线程怎么理解?所有的协程都是吗
作者回复: 对 单线程实现并发
2020-06-181 - 苹果asyncio.run() cannot be called from a running event loop 这个问题是如何解决,
作者回复: https://stackoverflow.com/questions/55409641/asyncio-run-cannot-be-called-from-a-running-event-loop
2020-02-021 - 隰有荷老师,在如下代码中: async def worker_2(): print('worker_2 start') await asyncio.sleep(2) print('worker_2 done') 其中的await asyncio.sleep(2)是否可以理解为在切出当前程序,2秒后再继续执行print('worker_2 done')代码? 那么如果我有个耗时任务 def xxx(): ...,那么该如何用await asyncio来让这个xxx函数运行并切出当前程序呢?
作者回复: 1. 基本是,但是注意是2秒后将当前断点加入协程池中等待调度。 2. 如果你只有这个耗时任务和当前任务(也就是总共两个任务),在当前任务调用 await 自动就切换到耗时任务了;但是当协程任务很多的时候,由于协程没有优先级设置,因此可能会出现耗时任务一直没有被分配资源的情况。实践中可以创建一个用于完成耗时任务的协程池,以限制耗时任务占用的总协程数量,于是就又回到了基于线程的并发模型中。
2019-11-281 - 扶幽请问下有木有相关的书籍,来进行这块的学习呢!有些原理性的东西还是没办法深入理解,谢谢。
作者回复: 最好的办法就是多实践。文中的原理性东西都已经讲了,你可以边实践,遇到问题再去google
2019-10-121 - cotter受教了,第一次听说这个高级功能! 我在工作中遇到一个需要并发的问题,用python在后台并发执行shell ,并发数量用时间范围控制,要不停的改时间分多次串行,方法比较笨拙。协程可以简化我的代码。 老师,并发很多事件应该也是需要消耗很多资源,协程改如何控制并发数量?
作者回复: 这个没有统一结论。需要根据硬件设置和具体线上的条件,进行测试莱选取最优的并发数量
2019-06-2431