优点:使用gevent协程,可以更好的利用线程资源。(基于线程实现)

需求:使用一个线程,去请求多个网站的资源(注意,请求上会有延时)<实际上是去请求了大量的网站信息,我们使用了多线程,只不过每个线程依旧会分配到多个网站资源,这里我们只需要去讨论这一条线程即可>

可以看出,由于网络延迟等因素,当我们去获取信息时,有一段时间呗浪费,用于空等信息返回,当我们去获取大量网站的时候,那这个时间是非常大的。我们需要去避免他。


解决方案:使用协程,充分利用我们中间等待的这一段时间,去做其他的事情,比如其请求下一个网站,,或者下几个网站。然后连续去接收信息,就可以充分的利用空耗的时间

1.协程的简单使用:

pip3 install gevent  # gevent模块若是没有,只需要先下载

开始使用:

import geventfrom gevent import monkey
monkry.patch_all()  #可以提高效率
def foo():print("foo函数开始运行")gevent.sleep(0)print("又回到了foo函数")def bar():print("bar函数开始运行")gevent.sleep(0)print("又回到了bar函数")gevent.joinall([gevent.spawn(foo),gevent.spawn(bar),
])

输出结果:foo函数开始运行
bar函数开始运行
又回到了foo函数
又回到了bar函数

2.协程的了解:对于上面的例子来说,有点不太容易理解,我们使用计时去了解其中流程,再去讨论上面代码

(1)上面sleep(0)和下面的sleep(3)相比,得出两个函数的执行时间是一致的(几乎是)

import gevent
import timebegin = time.time()def foo():fs = time.time() - beginprint("foo函数开始运行",fs)gevent.sleep(3)fe = time.time() - beginprint("又回到了foo函数",fe)def bar():bs = time.time() - beginprint("bar函数开始运行",bs)gevent.sleep(3)be = time.time() - beginprint("又回到了bar函数",be)gevent.joinall([gevent.spawn(foo),gevent.spawn(bar),
])

foo函数开始运行 0.01000070571899414
bar函数开始运行 0.01000070571899414
又回到了foo函数 3.0101723670959473
又回到了bar函数 3.0101723670959473

注意输出结果

我们可以看出两个函数都是在统一时间执行第一句输出,在三秒后去执行的第二句输出

(2)sleep(3)和sleep(1)

import gevent
import timebegin = time.time()def foo():fs = time.time() - beginprint("foo函数开始运行",fs)gevent.sleep(1)fe = time.time() - beginprint("又回到了foo函数",fe)def bar():bs = time.time() - beginprint("bar函数开始运行",bs)gevent.sleep(3)be = time.time() - beginprint("又回到了bar函数",be)gevent.joinall([gevent.spawn(foo),gevent.spawn(bar),
])

注意输出结果:几乎在同一时间执行两个函数(顺序和joinall方法中注册顺序有关),在我们设定的sleep时间后去继续执行函数

foo函数开始运行 0.0060002803802490234
bar函数开始运行 0.0060002803802490234
又回到了foo函数 1.0060575008392334
又回到了bar函数 3.006171941757202

所以说对于最上面简单使用中的执行顺序先是根据joinall的注册顺序去打印

foo函数开始运行
bar函数开始运行

然后由于sleep(0)间隔是0,所以立即去执行下面的打印程序(当sleep的时间是一致时,顺序还是和注册时一致)

又回到了foo函数
又回到了bar函数

(3)使用time.sleep()去更加深刻了解协程

import gevent
import timebegin = time.time()def foo():fs = time.time() - beginprint("foo函数开始运行",fs)gevent.sleep(1)time.sleep(4)  #这里睡眠4秒fe = time.time() - beginprint("又回到了foo函数",fe)def bar():bs = time.time() - beginprint("bar函数开始运行",bs)gevent.sleep(3)be = time.time() - beginprint("又回到了bar函数",be)gevent.joinall([gevent.spawn(foo),gevent.spawn(bar),
])

注意输出结果:发现对于我们在foo中设置的time.sleep(4)对bar方法也有影响。

foo函数开始运行 0.005000114440917969
bar函数开始运行 0.0060002803802490234
又回到了foo函数 5.006286144256592
又回到了bar函数 5.007286310195923

原因:gevent设置了我们协程的苏醒时间,但是当苏醒时间与我们的执行时间相冲突,那么会以执行时间为主(毕竟这是单线程,不会考虑其他的),而原来的设置的gevent.sleep(秒数)则变成了大小比较,谁在后,谁就后执行

任务框架:

import gevent
import timebegin = time.time()def foo(url,index):fs = time.time() - beginprint("%s:发送请求到%s,等待返回"%(index,url),fs) #这里可以模拟发送请求gevent.sleep(0)fe = time.time() - beginprint("%s:获取信息从%s,开始处理"%(index,url),fe) #这里模拟处理信息gevent.joinall([gevent.spawn(foo,"www.baidu.com",1),  #注意传参方式gevent.spawn(foo,"www.sina.com.sn",2),
])

输出结果:

1:发送请求到www.baidu.com,等待返回 0.005000114440917969
2:发送请求到www.sina.com.sn,等待返回 0.005000114440917969
1:获取信息从www.baidu.com,开始处理 0.005000114440917969
2:获取信息从www.sina.com.sn,开始处理 0.005000114440917969



补充:greenlet协程(gevent是基于greenlet实现,所以有必要去了解下)

from greenlet import greenletdef foo():print("开始执行foo")gr2.switch()print("又回到foo")gr2.switch()def bar():print("开始执行bar")gr1.switch()print("又回到bar")gr1 = greenlet(foo)
gr2 = greenlet(bar)
gr1.switch()    #以gr1开始执行,switch中也可以传递参数

输出结果:

开始执行foo
开始执行bar
又回到foo
又回到bar

转载于:https://www.cnblogs.com/ssyfj/p/9030165.html

python---基础知识回顾(十)进程和线程(协程gevent:线程在I/O请求上的优化)...相关推荐

  1. Python基础知识回顾

    python 基础汇总: 1.Python大小写敏感 2.Python是动态语言,即在定义变量时不需要指定变量类型 3.Python的整数合浮点数没有大小限制 4.python3 ,字符串是以Unic ...

  2. python基础知识有哪些需要背(记住是基础知识)我是初学者

    大家好,小编来为大家解答以下问题,一个有趣的事情,一个有趣的事情,今天让我们一起来看看吧! 1.python基础知识有哪些需要背(记住是基础知识)我是初学者 或看好Python的广阔前景,或看中Pyt ...

  3. 2.Python 基础知识

    文章目录 Python 基础知识 知识点一 : 注释 1.单行注释 2.多行注释 知识点二 : 变量 知识点三 : 数据类型 1.数字类型 1.1 整型 1.2 浮点型 1.3 复数类型 2.字符串 ...

  4. Python基础知识有哪些?你都知道吗

    Python基础知识有哪些?这几年,人工智能.数据分析等各行业的兴起,让更多人知道了Python,让Python是又火了一把.Python作为一个简介又实用的编程语言,让许多想从事信息技术行业的人准备 ...

  5. Python基础知识笔记——补充

    其实之前已经学过很多python基础了,甚至学了好多遍了,但最近报名了一个线上班,有空会看看一些视频,因此在本文补充一些以前漏学或者老师讲得不错的知识. 目录 Hash模块 简介 Base64 zli ...

  6. Python基础知识笔记

    文章目录 Python基础知识 教程:https://www.liaoxuefeng.com/wiki/1016959663602400 内置函数:https://docs.python.org/3/ ...

  7. Python基础知识总结

    1. Python基础知识 1.1  Python历史 1.1.1 Python起源 Python的作者,Guido von Rossum,荷兰人.1982年,Guido从阿姆斯特丹大学获得了数学和计 ...

  8. python基础知识整理

    1.列表去重 #方法一 def delList(L):L1 = [ ]for i in L:if i not in L1:L1.append(i)return L1 print(delList(L1) ...

  9. python基础知识整理-python爬虫基础知识点整理

    首先爬虫是什么? 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本. 根据我的经验,要学习Python爬虫 ...

  10. Java基础知识回顾之七 ----- 总结篇

    前言 在之前Java基础知识回顾中,我们回顾了基础数据类型.修饰符和String.三大特性.集合.多线程和IO.本篇文章则对之前学过的知识进行总结.除了简单的复习之外,还会增加一些相应的理解. 基础数 ...

最新文章

  1. 老男孩博客获三大搜素引擎搜索自然排名第一位(百度谷歌搜狗)
  2. 大写的服!用耳朵也能写代码?盲人程序员自学编程成为全栈工程师
  3. 【Flutter】ListView 列表高级功能 ( ScrollController 上拉加载更多 )
  4. 华为LTE 模块AT 命令拨号上网流程
  5. pycharm 取消连按两下shift出现的全局搜索
  6. ASP.NET Core 简单实现七牛图片上传(FormData 和 Base64)
  7. android 使用webview访问优酷无法播放视频的问题
  8. ubuntu18.10下面从视频中提取音频
  9. C#单元测试如何查看输出的调试信息?
  10. seafile安装教程 Linux,CentOS7安装seafile开源版
  11. C# LINQ学习笔记四:LINQ to OBJECT之操作文件目录
  12. win11打开控制面板闪退怎么办 Windows11控制面板闪退的解决方法
  13. 统计信号处理知识点总结_统计信号处理-简单看看克拉美罗界
  14. 添加.MSPX文件(VISTA下)
  15. (转)给趋势投资信仰充值:动量模型百年赚钱史
  16. WPF——GridView
  17. JAVA网站后台管理系统
  18. 走楼梯c语言程序,C语言项目爬楼梯的两种实现方法参考
  19. PLC通过DDE通讯——基于Codesys和组态王7.5进行数据采集
  20. 北京的购车摇号新政的概率分析

热门文章

  1. Nagios_快速配置
  2. 日历控件,可运行在XHTML1.0下
  3. 快乐大本营中测试声音年龄的软件_海天味极鲜酱油极限挑战宝藏行 终极试炼,极限成员们勇登珠峰大本营...
  4. spring整合cxf开发rest风格的webservice接口(客户端服务端)
  5. Python数据结构与算法(二)栈和队列
  6. python中collections中的counter类_了解Python的collections.Counter类型
  7. physx选择显卡还是cpu_3D建模和渲染吃CPU还是显卡?专业显卡和游戏显卡的区别...
  8. CentOS7.6安装WirёGuαrd(一)
  9. 北京房价研究(2017)
  10. 搞清字库表、编码字符集、字符编码