python第16天-网络4

协程

又叫微线程,coroutine,可以认为是比线程更小的执行单元,自带CPU上下文,。

通俗理解:在一个线程的某个函数,可以再任何地方保存当前函数的一些临时变量等信息,然后切换到另一个函数执行,并且切换的次数和什么时候再切换到原来的函数由开发者自己确定。

协程和线程差异

线程非常耗性能,从系统层面远不止保存和恢复CPU上下文,OS的每个线程都有自己缓存Cache等数据等。协程的切换只是单纯操作CPU上下文

# coding=utf-8
import time
import sys
sys.setrecursionlimit(10000)

def A():
    while True:
        print("---A---")
        yield
        time.sleep(0.5)

def B(c):
    while True:
        print("---B---")
        c.__next__()
        time.sleep(0.5)

if __name__=="__main__":
    a=A()
    B(a)

运行结果

---B---
---A---
---B---
---A---
---B---
---A---
---B---
---A---

但是用生成器来做协程感觉不是很优美,greenlet

sudo pip install greenlet#python3导入pip3

#coding=utf-8

from greenlet import greenlet
import time

def test1():
	while True:
		print("---A---")
		gr2.switch()
		time.sleep(0.5)

def test2():
	while True:
		print("---B---")
		gr1.switch()
		time.sleep(0.5)

gr1 = greenlet(test1)
gr2 = greenlet(test2)

#切换到gr1中运行
gr1.switch()

greenlet的底层代码由C语言写的,运行结果一样

gevent比greenlet更强大,自动切换任务,原理是当一个greenlet遇到耗时操作如访问网络时,会自动切换到其他greenlet,操作完成再切换回来继续执行。

#coding=utf-8
import gevent

def f(n):
	for i in range(n):
		print gevent.getcurrent(), i

g1 = gevent.spawn(f, 5)
g2 = gevent.spawn(f, 5)
g3 = gevent.spawn(f, 5)
g1.join()
g2.join()
g3.join()

运行结果:3个greenlet依次运行而不是交替运行

<Greenlet at 0x10e49f550: f(5)> 0
<Greenlet at 0x10e49f550: f(5)> 1
<Greenlet at 0x10e49f550: f(5)> 2
<Greenlet at 0x10e49f550: f(5)> 3
<Greenlet at 0x10e49f550: f(5)> 4
<Greenlet at 0x10e49f910: f(5)> 0
<Greenlet at 0x10e49f910: f(5)> 1
<Greenlet at 0x10e49f910: f(5)> 2
<Greenlet at 0x10e49f910: f(5)> 3
<Greenlet at 0x10e49f910: f(5)> 4
<Greenlet at 0x10e49f4b0: f(5)> 0
<Greenlet at 0x10e49f4b0: f(5)> 1
<Greenlet at 0x10e49f4b0: f(5)> 2
<Greenlet at 0x10e49f4b0: f(5)> 3
<Greenlet at 0x10e49f4b0: f(5)> 4

gevent切换执行

#coding=utf-8
import gevent

def f(n):
	for i in range(n):
		print gevent.getcurrent(), i
		#⽤来模拟⼀个耗时操作, 注意不是time模块中的sleep
		gevent.sleep(1)
g1 = gevent.spawn(f, 5)
g2 = gevent.spawn(f, 5)
g3 = gevent.spawn(f, 5)
g1.join()
g2.join()
g3.join()

运行结果 3个greenlet交替运行

<Greenlet at 0x7fa70ffa1c30: f(5)> 0
<Greenlet at 0x7fa70ffa1870: f(5)> 0
<Greenlet at 0x7fa70ffa1eb0: f(5)> 0
<Greenlet at 0x7fa70ffa1c30: f(5)> 1
<Greenlet at 0x7fa70ffa1870: f(5)> 1
<Greenlet at 0x7fa70ffa1eb0: f(5)> 1
<Greenlet at 0x7fa70ffa1c30: f(5)> 2
<Greenlet at 0x7fa70ffa1870: f(5)> 2
<Greenlet at 0x7fa70ffa1eb0: f(5)> 2
<Greenlet at 0x7fa70ffa1c30: f(5)> 3
<Greenlet at 0x7fa70ffa1870: f(5)> 3
<Greenlet at 0x7fa70ffa1eb0: f(5)> 3
<Greenlet at 0x7fa70ffa1c30: f(5)> 4
<Greenlet at 0x7fa70ffa1870: f(5)> 4
<Greenlet at 0x7fa70ffa1eb0: f(5)> 4

gevent版服务器 monkey打补丁,动态修改下边的代码

原文地址:https://www.cnblogs.com/wangjinliang1991/p/9898905.html