协程

协程:微线程,协程是一种用户态的轻量级线程。遇到IO操作就切换。
代码前戏:使用yield实现协程的简单例子

import time,queue
def consumer(name):
    print("--->starting eating 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 n < 6:
        print("\033[32;1m[producer]\033[0m is making baozi %s" % n)
        con.send(n)
        con2.send(n)
        n += 1

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

# 这里输出是同时打印所有返回结果,就是协程的简单例子

 

协程特点:

1、必须在只有一个单线程里实现并发
2、修改共享数据不需加锁
3、用户程序里自己保存多个控制流的上下文栈
4、一个协程遇到IO操作自动切换到其它协程
· greenlet是一个用C实现的协程模块,相比与python自带的yield,它可以使你在任意函数之间随意切换,而不需把这个函数先声明为generator。但greenlet无法实现遇到IO自动切换。
代码范例1:greenlet手动挡开车

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是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中用到的主要模式是Greenlet。
代码范例2:gevent自动挡开车(遇到IO自动切换,gevent.sleep()为模拟IO)

import gevent
def func1():
    print("func1 action...")
    gevent.sleep(2)
    print("func1 finish...")
def func2():
    print("func2 action...")
    gevent.sleep(1)
    print("func2 finish...")
def func3():
    print("func3 action...")
    gevent.sleep()
    print("func3 finish...")
gevent.joinall([
    gevent.spawn(func1),
    gevent.spawn(func2),
    gevent.spawn(func3)
])

# 输出:
func1 action...
func2 action...
func3 action...
func3 finish...
func2 finish...
func1 finish...

代码号外:爬取网站主页

from urllib import request
def func(url):
    print("GET: %s" % url)
    res = request.urlopen(url)
    data = res.read()
    f = open("url.html",'wb')
    f.write(data)
    f.close()
    print("%d bytes received from %s." % (len(data), url))
func('http://zhihu.com')

代码范例3:串行/并行爬取多个网页数据

from urllib import request
import gevent, time
from gevent import monkey
monkey.patch_all()   # 将当前程序所有的IO操作都做上标记

def func(url):
    print("GET: %s" % url)
    res = request.urlopen(url)
    data = res.read()
    print("%d bytes received from %s." % (len(data), url))

urls = [
    'https://www.python.org',
    'https://www.yahoo.com',
    'https://www.github.com' ]
time_start = time.time()
for url in urls:
    func(url)   # 串行
print("Serial cose: ",time.time() - time_start)

async_time_start = time.time()
gevent.joinall([   # 并行(异步)
    gevent.spawn(func,'https://www.python.org'),
    gevent.spawn(func,'https://www.yahoo.com'),
    gevent.spawn(func,'https://www.github.com')
])
print("async cose: ",time.time() - async_time_start)
# 由执行结果可知,并行花费时间明显少于串行。

 

转载于:https://www.cnblogs.com/fone933/p/8035075.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值