Python3基础-协程

  • 协程

协程,又称微线程,纤程。英文名Coroutine。 非抢占式的程序

          A-->B-->A--》B

协程主要解决的就是IO操作的

协程:本质上就是一个线程

协程的优势:

   1、没有切换的消耗

   2、没有锁的概念

 

优点1: 协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。

优点2: 不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。

 

因为协程是一个线程执行,那怎么利用多核CPU呢?最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。

  • 协程的关键词 ---》yield的实现

yield首先是个return,普通的return是什么意思,就是在程序中返回某个值,返回之后程序就不再往下运行了。看做return之后再把它看做一个是生成器(generator)的一部分(带yield的函数才是真正的迭代器)

def foo():
    print("string.....")
    while True:
        res = yield  4
        print("res:",res)

g = foo()
print(next(g))
print("*"*20)
print(g.send(7))

执行结果如下:

string.....
4
********************
res: 7
4

这就结束了,说一下,为什么用这个生成器,是因为如果用List的话,会占用更大的空间,比如说取0,1,2,3,4,5,6............1000

你可能会这样:

for n in range(1000):
    a=n

这个时候range(1000)就默认生成一个含有1000个数的list了,所以很占内存。

这个时候你可以用刚才的yield组合成生成器进行实现,也可以用xrange(1000)这个生成器实现

yield组合:

def  foo(num):
    print("starting.....")
    while num < 10:
        num = num + 1
        yield  num

for n in foo(0):
    print(n)

以上结果如下:

starting.....
1
2
3
4
5
6
7
8
9
10

 yield的简单实现

import time
import queue

def consumer(name):
    print("--->ready to eat baozi...")
    while True:
        new_baozi = yield
        print("[%s] is eating baozi %s" % (name,new_baozi))
        #time.sleep(1)

def producer():

    r = con.__next__()
    r = con2.__next__()
    n = 1
    while 1:
        time.sleep(1)
        print("\033[32;1m[producer]\033[0m is making baozi %s and %s" %(n,n+1) )
        con.send(n)
        con2.send(n+1)
        n +=2


if __name__ == '__main__':
    con = consumer("c1")
    con2 = consumer("c2")
    p = producer()

结果如下:

--->ready to eat baozi...
--->ready to eat baozi...
[producer] is making baozi 1 and 2
[c1] is eating baozi 1
[c2] is eating baozi 2
[producer] is making baozi 3 and 4
[c1] is eating baozi 3
[c2] is eating baozi 4
[producer] is making baozi 5 and 6
[c1] is eating baozi 5
[c2] is eating baozi 6
[producer] is making baozi 7 and 8
[c1] is eating baozi 7
[c2] is eating baozi 8
[producer] is making baozi 9 and 10
[c1] is eating baozi 9
[c2] is eating baozi 10

Greenlet

greenlet是一个用C实现的协程模块,相比与python自带的yield,它可以使你在任意函数之间随意切换,而不需把这个函数先声明为generator

from greenlet import greenlet


def test1():
    print(12)
    gr2.switch()
    print(34)
    gr2.switch()


def test2():
    print(56)
    gr1.switch()
    print(78)


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

执行结果如下:

12
56
34
78

Gevent

import gevent

import requests,time


start=time.time()

def f(url):
    print('GET: %s' % url)
    resp =requests.get(url)
    data = resp.text
    f = open("new","w",encoding="utf-8")
    f.write(data)
    print('%d bytes received from %s.'%(len(data), url))


gevent.joinall([

        gevent.spawn(f, 'https://www.python.org/'), #  # 创建一个协程
        # gevent.spawn(f, 'https://www.yahoo.com/'),
        gevent.spawn(f, 'https://www.baidu.com/'),
        gevent.spawn(f, 'https://www.sina.com.cn/'),

])
#
# f('https://www.python.org/')
# f('https://baidu.com/')
# f('https://www.sina.com.cn/')

print("cost time:",time.time()-start)

 

https://www.cnblogs.com/yuanchenqi/acticles/6248025.html

posted @ 2020-11-02 14:31  槑槑DE  阅读(143)  评论(0)    收藏  举报