很古老的用法了,现在大多用的aiohttp库实现,这篇记录仅仅用做个人的协程底层实现的学习。

争取用看得懂的字来描述问题。

1.什么是yield

如果还没有怎么用过的话,直接把yield看做成一种特殊的return(PS:本质 generator(生成器))

return是返回一个值然后就终断函数了,而yield返回的是一个生成器(PS:不知道的直接看作特殊列表,看下面的代码案例)

# -*- coding: utf-8 -*-
# @Time : 2022/11/10 16:17
# @Author : 红后
# @Email : not_enabled@163.com
# @blog : https://www.cnblogs.com/Red-Sun
# @File : 实例1.py
# @Software: PyCharm def main():
'''
遍历0到4,这五个数,并分别打印
'''
for num in range(5):
yield num if __name__ == '__main__':
for num in main():
print(num)
print('-'*50)
for num in [0, 1, 2, 3, 4]:
print(num)



将它看作列表用for循环遍历,就能取出其中的值。

2.yield于列表的区别

它与原来列表的区别就在于,自带的列表是固定的,而把yield看作列表的话是动态的。

具体案例描述请看代码及备注(PS:个人自己描述的,有不对的地方望各位指点)

# -*- coding: utf-8 -*-
# @Time : 2022/11/14 13:24
# @Author : 红后
# @Email : not_enabled@163.com
# @blog : https://www.cnblogs.com/Red-Sun
# @File : 实例2.py
# @Software: PyCharm def main():
'''
将yield看作一个动态列表,从yield左往右为传出数据,从又往左为传入数据。
PS:有yield存在的那一行,需要从左往右传出数据跑一遍,数据出去以后又要从又往左带接收的数据跑一遍,一共一行跑两边(仅作者个人记忆方法)
'''
num1 = yield
num2 = yield
print(num1, num2)
yield num1 + num2
if __name__ == '__main__':
a = main()
# 第一个next对应第一个yield的右边为空即None,所以动态列表中加入一个参数为None,返回值为列表的-1位是None
print(next(a)) # [None]
# 第二个通过send方法传入一个数1,即在上一次停止的地方从右往左传入参数,所以给num1赋值为1.然后继续找下一个yield,其右边的值依旧为None,加入动态列表,此时返回值-1位依旧是None
print(a.send(1)) # [None, None]
# 第三通过send方法传入一个数2,即在上一次停止的地方从右往左传入参数,所以给num2赋值为2.然后继续找下一个yield,其右边的值为num1 + num2,此时num1为1,num2为2,计算得返回值-1位为3
print(a.send(2)) # [None, None, num1 + num2]

3.yield from 实现协程

yield from 后面需要加可迭代对象

当它后面加上生成器(上述所说的yield这种)便可以实现生成的嵌套

  1. 老板(主程序):调用委派生成器
  2. 包工头(委派生成器):包含yield from表达式的生成器
  3. 打工仔(子生成器):生成器函数

其中委派生成器的作用:在主程序与子生成器之间建立一个双向通道。

所谓双向通道是指,主程序可以将参数通过send传递给子生成器,子生成器的yield的值也可以直接返回给主函数。(PS:委派生成器只有创建通道的作用,没有拦截数据这种功能)

也许有人会想直接用主程序调用子生成器不就行了,而对这的解释是,使用yield from作为中间过渡是为了让它帮我们进行异常处理(PS:类似写程序为了正常运行加上try一个道理)

# -*- coding: utf-8 -*-
# @Time : 2022/11/10 15:13
# @Author : 红后
# @Email : not_enabled@163.com
# @blog : https://www.cnblogs.com/Red-Sun
# @File : coroutines.py
# @Software: PyCharm import requests def coroutines_spider():
'''
子生成器(PS: 打工仔,真正干活的)
'''
response = None # 首次激活返回None,后期网页响应覆盖
while True:
url = yield response
response = requests.get(url) def appoint():
'''
委派生成器,委托子生成器完成具体任务 (PS: 类似包工头负责劳务派遣)
'''
while True:
yield from coroutines_spider() # 建立子生成器和主函数的双通道 def main(url_list: list):
'''
主函数(PS: 相当于老板,张贴招人启示)
'''
ul = appoint() # 创建委派生成器
next(ul) # 激活它
for url in url_list:
response = ul.send(url) # 将url作为参数传递进入子生成器中,返回子生成器yield出来的response
print(response.url, response.status_code) # 打印出response中的链接和状态码 if __name__ == '__main__':
url_list = ['https://www.baidu.com/', 'https://www.4399.com/', 'https://cn.bing.com/', ]
main(url_list=url_list)

Python用yield form 实现异步协程爬虫的更多相关文章

  1. 深入理解协程(二):yield from实现异步协程

    原创不易,转载请联系作者 深入理解协程分为三部分进行讲解: 协程的引入 yield from实现异步协程 async/await实现异步协程 本篇为深入理解协程系列文章的第二篇. yield from ...

  2. 小爬爬4.协程基本用法&&多任务异步协程爬虫示例(大数据量)

    1.测试学习 (2)单线程: from time import sleep import time def request(url): print('正在请求:',url) sleep() print ...

  3. Python核心框架tornado的异步协程的2种方式

    什么是异步? 含义 :双方不需要共同的时钟,也就是接收方不知道发送方什么时候发送,所以在发送的信息中就要有提示接收方开始接收的信息,如开始位,同时在结束时有停止位 现象:没有共同的时钟,不考虑顺序来了 ...

  4. python爬虫--多任务异步协程, 快点,在快点......

    多任务异步协程asyncio 特殊函数: - 就是async关键字修饰的一个函数的定义 - 特殊之处: - 特殊函数被调用后会返回一个协程对象 - 特殊函数调用后内部的程序语句没有被立即执行 - 协程 ...

  5. 深入理解协程(三):async/await实现异步协程

    原创不易,转载请联系作者 深入理解协程分为三部分进行讲解: 协程的引入 yield from实现异步协程 async/await实现异步协程 本篇为深入理解协程系列文章的最后一篇. 从本篇你将了解到: ...

  6. based on Greenlets (via Eventlet and Gevent) fork 孙子worker 比较 gevent不是异步 协程原理 占位符 placeholder (Future, Promise, Deferred) 循环引擎 greenlet 没有显式调度的微线程,换言之 协程

    gevent GitHub - gevent/gevent: Coroutine-based concurrency library for Python https://github.com/gev ...

  7. python协程与异步协程

    在前面几个博客中我们一一对应解决了消费者消费的速度跟不上生产者,浪费我们大量的时间去等待的问题,在这里,针对业务逻辑比较耗时间的问题,我们还有除了多进程之外更优的解决方式,那就是协程和异步协程.在引入 ...

  8. 消息/事件, 同步/异步/协程, 并发/并行 协程与状态机 ——从python asyncio引发的集中学习

    我比较笨,只看用await asyncio.sleep(x)实现的例子,看再多,也还是不会. 已经在unity3d里用过coroutine了,也知道是“你执行一下,主动让出权限:我执行一下,主动让出权 ...

  9. python爬虫---单线程+多任务的异步协程,selenium爬虫模块的使用

    python爬虫---单线程+多任务的异步协程,selenium爬虫模块的使用 一丶单线程+多任务的异步协程 特殊函数 # 如果一个函数的定义被async修饰后,则该函数就是一个特殊的函数 async ...

随机推荐

  1. C#使用Spire.Pdf包对PDF文档进行数字签名

    背景 对PDF文档进行数字签名的需求 对PDF文档添加水印的需求 网上资料版本不一或不全 本文章提到的Spire.Pdf均是使用的Spire.Pdf for .NET,除此之前还有其他语言的版本,如S ...

  2. 【必知必会】手把手教你配置MySQL环境变量——图文详解

    一.先决条件 假设我们已经成功安装MySQL数据库.如果还有小伙伴不知道如何安装MySQL数据库,可以在本文下留言,留言数超20,则出一期"手把手教你安装MySQL数据库--图文详解&quo ...

  3. ar9485 win10 笔记本电脑 无线网间歇性掉线

    问题  新安装了系统,刚开始上网正常,下载东西或者待机一段时间后掉线了. wifi都能搜到,就是连不上,重启电脑可以解决,但是每次重启很麻烦,必须找到治本的方法. 排除问题 1.手机连接没有问题,排除 ...

  4. KingbaseESV8R6 垃圾回收原理以及如何预防膨胀

    背景 KingbaseESV8R6支持snapshot too old 那么实际工作中,经常看到表又膨胀了,那么我们讨论一下导致对象膨胀的常见原因有哪些呢? 未开启autovacuum 对于未开启au ...

  5. K8S_CNI

    CNI 插件 定义: Container Network Interface 容器通用接口 K8S 中可选的 CNI 插件如下: Flannel 较流行 Calico 性能棒,比Flannel快1% ...

  6. Go编译过程

    一. Go编译流程 二.过程说明 1. 词法解析 读取Go源文件,将字符序列转换为符号(token)序列,比如将":="转换为_Define 代码中的标识符.关键字.运算符和分隔符 ...

  7. WinForm完美实现Cefsharp-v49控件C#与JS交互,并且可加载运行flash

    https://blog.csdn.net/zhao331863874/article/details/117328415

  8. MySQL集群搭建(1)-主备搭建

    数据库在任何业务中都是最重要的环节之一,这就对数据库架构提出的较高的要求.单点数据库永远不应该出现在生产环境,我们已经目睹过太多由于单点.备份缺失造成的损失,所以,搭建高可用 MySQL 集群是非常有 ...

  9. 苹果手机安装郑好办手机app后给绿城通公交卡充值的步骤

    1.苹果手机,需要带有NFC功能 苹果XS手机该功能默认是开启的,不用额外的其他操作 苹果11该功能需要设置开启才行.步骤:设置--通用--NFC,然后开启 2,公交卡 如下这种的公交卡可以充值: 如 ...

  10. 延申三大问题中的第三个问题处理---发布更新时先把服务从注册中心给down下来,等待一段时间后再能更新模块

    一开始采取的思路大致如下: 在preStop中使用/bin/sh命令,先down 然后sleep一段时间, 这种思路的执行情况如下: 假若升级容器使用的镜像版本的话,先执行preStop中的命令,sl ...