1.协程初识,greenlet模块

2.gevent模块(需要pip安装)

一.协程初识,greenlet模块:


协程:是单线程下的并发,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。

greenlet模块要自己用pip安装

#协程:
#本质上是一个线程
#能够在多个任务之间切换来节省一些IO时间
#协程中任务之间的切换也消耗时间,但是开销远远小于进程线程之间的切换 #协程的意义:
#在遇到IO操作的时候,切换到另外一个任务
#规避之前任务的IO时间,来提高cpu的利用率
#在实际工作中会采用:进程+线程+协程,来提高代码的并发效果
#进程是cpu核数+1,线程是cpu核数*5,每个线程中协程最多可以起500个
#比如:
#发送了一个网页请求后,在网络延时,等待网页响应的时间(等待IO),就可以用协程去切换任务利用等待的时间,继续发送多个网页请求,从而提高效率
#进程5,线程20,协程500 = 总共可以有50000个协程:一台4c的机器最多可以接收的并发数
#数据库,负载均衡,让很多个请求,平均分摊给各个服务器
#nginx组件 大型互联网公司会用到,就是用来帮你分发任务的,并发最大承载量就是50000,用的就是协程机制
#一般情况下就是根据这个规则,上下浮动 #协程的调度是由gevent完成的,而进程和线程的调度是cpu完成的 #greenlet以后都不怎么样,协程还是主要用gevent
#真正的协程模块就是使用greenlet完成的切换
from greenlet import greenlet
def eat():
print('eating')
g2.switch() #切换到g2运行g2,切记录当前g1运行的位置,切换后,如果g2那没切换回来,后面这句 print('eat end') 就不会运行了
print('eat end') def play():
print('playing')
g1.switch()
print('play end') g1 = greenlet(eat)
g2 = greenlet(play)
g1.switch() # def play2():
# print('playing')
# g1.switch()
# print('play end')
#
# def ch():
# play2.__name__ = 'play3'
# ch()
# print(play2.__name__)

协程初识-greenlet模块

#协程
#由于cpython解释器中的GIL原因,导致python中多线程被弱化了,而且切换多个线程之间也要时间开销
#所以就出现了协程,协程的切换效率更快,把1个线程的作用发挥到了极致,提高1个cpu的利用率。减少线程的时间开销
#java里也有协程,但是没有这么被重视

二.gevent模块


安装:pip3 install gevent

Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。

#切记 from gevent import monkey;monkey.patch_all()  这句话一定要写在想更改的模块前面

#GKX
#gevent模块 join,joinall,value,spawn
#协程适用于网络延迟的时候,也就是适合做爬虫的时候 ,或者socket连接的时候。代码如果没有高IO,没必要用协程
#gevent只会识别它认识的IO操作
from gevent import monkey;monkey.patch_all() #monkey这句话一定要写在想更改的模块前面
import time #通过猴子补丁,让sleep不阻塞
import gevent
import threading
# 用过gevent就会知道,会在最开头的地方gevent.monkey.patch_all();把标准库中的thread/socket等给替换掉.
# 这样我们在后面使用socket的时候可以跟平常一样使用,无需修改任何代码,但是它变成非阻塞的了. from greenlet import greenlet
def eat():
print(threading.current_thread().getName()) #>>DummyThread-1 dummy(仿制品)
print('eating')
time.sleep(1) #使用猴子补丁后,相当于 gevent.sleep
# gevent.sleep(1)
print('eat end') def play():
print(threading.current_thread().getName())
print('playing')
# time.sleep(1)
gevent.sleep(1)
print('play end')
g1 = gevent.spawn(eat) #开启一个协程, spawn(大量生产意思)
g2 = gevent.spawn(play)
g1.join() #让线程等待协程的结果,如果没有join,线程执行完毕后直接关闭,等不到协程的结果
g2.join()
print('')
#遇到sleep后会非阻塞,先执行其他任务,然后再同时来sleep1秒来打印任务
#有了gevent和猴子补丁,只要把函数注册进 gevent模块里,就可以使用协程了,其他都不用管
#当遇到IO会自动帮你切换到其他任务,最后再一起共享,所有任务的IO操作 #遇到IO—执行其他任务—其他任务执行到也遇到了IO——继续执行其他任务—都遇到了IO—在IO之间来回切换,看谁解除了IO,马上继续运行
#从而把等待IO的时间,用来执行任务。然后共享IO时间,达到提高效率的目的
#我们可以不用理会gevent的执行过程,注册完线程运行等待结果就好了

gevent模块-例子和解释

from gevent import monkey;monkey.patch_all() #monkey这句话一定要写在想更改的模块前面
import time #通过猴子补丁,让sleep不阻塞
import gevent
import threading
#同步和异步
def task():
time.sleep(0.5)
print('') def sync():
for i in range(10):
task() def a_sync():
g_lst = []
for i in range(10):
g = gevent.spawn(task)
g_lst.append(g)
gevent.joinall(g_lst) # == for g in g_lst:g.join() sync()
a_sync()

同步和异步的比较

# monkey patch指的是在运行时动态替换,一般是在startup的时候.
# 用过gevent就会知道,会在最开头的地方gevent.monkey.patch_all();把标准库中的thread/socket等给替换掉.
# 这样我们在后面使用socket的时候可以跟平常一样使用,无需修改任何代码,但是它变成非阻塞的了.
# 之前做的一个游戏服务器,很多地方用的import json,后来发现ujson比自带json快了N倍,
# 于是问题来了,难道几十个文件要一个个把import json改成import ujson as json吗?
# 其实只需要在进程startup的地方monkey patch就行了.是影响整个进程空间的.同一进程空间中一个module只会被运行一次.
# 下面是代码: # import json
# import ujson
#
# def monkey_patch_json():
# json.__name__ = 'ujson'
# json.dumps = ujson.dumps
# json.loads = ujson.loads
#
# monkey_patch_json()
#
# print
# 'main.py', json.__name__
# import sub
#
#
# import json
# print 'sub.py',json.__name__ # 最后,注意不能单纯的json = ujson来替换.

猴子补丁

用gevent模块实现的socket服务端的并发:

from gevent import monkey;monkey.patch_all()

from gevent import monkey;monkey.patch_all()
import gevent def func(conn):
conn.send(b'hello')
msg = conn.recv(1024).decode('utf8')
print(msg)
conn.close() #关闭如果放在循环里,就马上关闭了,没有连接的意义 while True:
conn, addr = sk.accept() #在这里阻塞,一直监听,一旦有client连接,马上把conn扔给一个并发。然后继续循环,阻塞
g = gevent.spawn(func,conn) sk.close()

server端

import time
import socket
sk = socket.socket()
sk.connect(('127.0.0.1',8080)) print(sk.recv(1024))
msg = input('>>>> ').encode('utf8')
sk.send(msg)
sk.close()

client端

协程----greenlet模块,gevent模块的更多相关文章

  1. 网络编程基础--协程--greenlet切换---gevent自动识别 IO ---

    协程: 1 单线程来实现并发---协程: 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程, 即协程是由用户程序自己控制调度的 只 ...

  2. 协程greenlet、gevent

    greenlet为了更好使用协程来完成多任务,python中greenlet模块对其封装,从而使得切换任务变得更加简单安装方式 pip3 install greenlet 示例代码: from gre ...

  3. Python的requests、greenlet和gevent模块在windows下安装

    一.requests模块在windows下安装 Linux系统下requests的安装方法在http://docs.python-requests.org/en/latest/user/install ...

  4. python 线程(其他方法,队列,线程池,协程 greenlet模块 gevent模块)

    1.线程的其他方法 from threading import Thread,current_thread import time import threading def f1(n): time.s ...

  5. python 全栈开发,Day43(引子,协程介绍,Greenlet模块,Gevent模块,Gevent之同步与异步)

    昨日内容回顾 I/O模型,面试会问到I/O操作,不占用CPU.它内部有一个专门的处理I/O模块.print和写log 属于I/O操作,它不占用CPU 线程GIL保证一个进程中的多个线程在同一时刻只有一 ...

  6. 14 并发编程-(协程)-greenlet模块&gevent模块

    1.实现多个任务之间进行切换,yield.greenlet都没有实现检测I/O,greenlet在实现多任务切换下更简单 from greenlet import greenlet def eat(n ...

  7. 并发编程~~~协程~~~greenlet模块, gevent模块

    一 协程 1. 协程: 单线程下的并发,又称微线程,纤程.协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 并发真正的核心: 切换并且保持状态. 开启协程并发的执行,自己的程序把控着C ...

  8. Python之路(第四十七篇) 协程:greenlet模块\gevent模块\asyncio模块

    一.协程介绍 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 协程相比于线程,最大的区别在于 ...

  9. 协程介绍, Greenlet模块,Gevent模块,Genvent之同步与异步

    昨日内容回顾 I/O模型,面试会问到I/O操作,不占用CPU.它内部有一个专门的处理I/O模块.print和写log 属于I/O操作,它不占用CPU 线程GIL保证一个进程中的多个线程在同一时刻只有一 ...

随机推荐

  1. 这5个实用技巧,教你设计出更好的App

    三年前,谷歌公司分享了一项研究:用户平均会安装36个app在手机上,但每天都使用的只有9个.据统计,只有4%的app会被使用一年以上. 所以,能运用基本用户体验设计原则来设计出更好的app,对公司大有 ...

  2. 使用new和newInstance()创建类的区别

    在初始化一个类,生成一个实例的时候,newInstance()方法和new关键字除了一个是方法,一个是关键字外,最主要有什么区别?它们的区别在于创建对象的方式不一样,前者是使用类加载机制,后者是创建一 ...

  3. larave----------通过composer.json下载laravel包----barryvdh/laravel-debugbar

    1.去Packagist网站https://packagist.org/packages/barryvdh/laravel-debugbar#dev-master找到

  4. Docker 推送镜像到hub.docker

    1.Docker镜像文件:lails.server.demo:1.0, 2.登录Docker:docker login[根据提示输入用户名/密码] 3.执行:docker push lails.ser ...

  5. linux 生成密钥,并向git服务器导入公钥

    1.      server1 上使用haieradmin用户 ,先清理之前的ssh登录记录,rm –rf ~/.ssh , 运行ssh-keygen –t rsa(只需回车下一步即可,无需输入任何密 ...

  6. 以选项卡的故事扯扯js面向对象

    在现在的网页中,选项卡(我自己这样子叫)是非常普遍的,也是比较基础,学了原型实现选项卡也挺久了,最近在学ES6,学了用类实现选项卡,今天就在此做个总结,别的废话也不多说. 以"貌" ...

  7. 第三篇——Struts2的动态方法调用

    Struts2动态方法调用 默认方式:默认执行方法中的execute方法,若指定类中没有该方法,默认返回success: method方式:执行method属性中定义的方法,没有该方法,页面报错: 通 ...

  8. vue运行时 eslint 报“import/first” WARN deprecated browserslist 问题解决

    vue运行时 eslint 报“import/first”  WARN deprecated browserslist 问题解决 这个信息的意思是导入文件顺序不对,绝对导入应该放在相对导入前面.将绝对 ...

  9. P3371 【模板】单源最短路径(弱化版)(Dijkstra算法)

    题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入输出格式 输入格式: 第一行包含三个整数N.M.S,分别表示点的个数.有向边的个数.出发点的编号. 接下来M行每行包含三 ...

  10. BIOS备忘录之EC常用知识点

    BIOS工程师眼中常用的EC知识点汇总: EC的硬件架构 EC硬件结构上主要分为两部分:Host Domain和EC Domain Host Domain就是通过LPC与CPU通信的部分(LPC部分需 ...