协程

如何实现两个函数之间的切换呢,在之前我们可以这样实现:

def func():
    print(1)
    yield
    print(3)
    yield
def fu():
    a=func()
    next(a)
    print(2)
    next(a)
    print(4)
fu()




C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/day40/40.py
1
2
3
4

Process finished with exit code 0

 

使用这种方法写一个生产者消费者模型

def func():
    while 1:
        n=yield
        print('吃%s包子'%n)
def fun():
    a=func()
    next(a)
    for i in range(10):
        print('包子%s熟了'%i)
        a.send(i)

fun()





C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/day40/40.py
包子0熟了
吃0包子
包子1熟了
吃1包子
包子2熟了
吃2包子
包子3熟了
吃3包子
包子4熟了
吃4包子
包子5熟了
吃5包子
包子6熟了
吃6包子
包子7熟了
吃7包子
包子8熟了
吃8包子
包子9熟了
吃9包子

Process finished with exit code 0

 

如何在单线程中切换呢?这个时候我们需要引用一个模块

greenlet

执行后看不到效果,是因为太快了,快到来不及打印,所以,我们让它睡一会就好了,

from  greenlet import greenlet
import time
def func():
    print('对8')
    f1.switch()
    time.sleep(1)
    print('对9')
    f1.switch()
def fu():
    print('三带一')

    f.switch()
    time.sleep(1)
    print('王炸')


f=greenlet(func)
f1=greenlet(fu)
f.switch()


C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/day40/40.py
对8
三带一
对9
王炸

Process finished with exit code 0

在代码之间来回切换会降低效率

另外,在yield,greenlet中,切换不能规避IO时间:

如果想要规避IO时间,又要使用一个模块:gevevnt

下面这是gevent版本的实现切换功能:

from  gevent import monkey;monkey.patch_all()
import time
import gevent
def func():
    print('11')
    gevent.sleep(2)
    print('33')
def fu():
    print('22')
    gevent.sleep(2)
    print('44')
g=gevent.spawn(func)
g1=gevent.spawn(fu)
gevent.joinall([g,g1])



C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/day40/40.py
11
22
33
44

Process finished with exit code 0

gevent遇见它能识别的IO它就执行,但是如果不认识,就切换不了:

# from  gevent import monkey;monkey.patch_all()
import time
import gevent
def func():
    print('11')
    time.sleep(2)
    # gevent.sleep(2)
    print('33')
def fu():
    print('22')
    # gevent.sleep(2)
    time.sleep(2)
    print('44')
g=gevent.spawn(func)
g1=gevent.spawn(fu)
gevent.joinall([g,g1])


C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/day40/40.py
11
33
22
44

Process finished with exit code 0

 

如何解决这个问题?

请用gevent中的monkeyn中的monkey.patch_all()

from  gevent import monkey;monkey.patch_all()
import time
import gevent
def func():
    print('11')
    time.sleep(2)
    # gevent.sleep(2)
    print('33')
def fu():
    print('22')
    # gevent.sleep(2)
    time.sleep(2)
    print('44')
g=gevent.spawn(func)
g1=gevent.spawn(fu)
gevent.joinall([g,g1])

C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/day40/40.py
11
22
33
44

Process finished with exit code 0
from  gevent import monkey;monkey.patch_all()
import time
import gevent
from  threading import  current_thread
def func():
    print(current_thread().name)#线程名
    print('11')
    time.sleep(2)
    # gevent.sleep(2)
    print('33')
def fu():
    print('22')
    # gevent.sleep(2)
    time.sleep(2)
    print('44')
g=gevent.spawn(func)
g1=gevent.spawn(fu)
gevent.joinall([g,g1])


C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/day40/40.py
DummyThread-1
11
22
33
44

Process finished with exit code 0

 

 

 

二,效率对比

from  gevent import monkey;monkey.patch_all()
import time
import gevent
def func(args):
    time.sleep(1)
    print(args)
def fun():
    for i in range(10):
        func(i)
def fu():
    l=[]
    for i in range(10):
        l.append(gevent.spawn(func,i))
    gevent.joinall(l)

start=time.time()
fun()
print(time.time()-start)
start=time.time()
fu()
print(time.time()-start)



C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/day40/40.py
0
1
2
3
4
5
6
7
8
9
10.008541107177734
0
1
2
3
6
5
4
7
8
9
1.002117395401001

Process finished with exit code 0

 

 

 

爬取网址的效率对比

from gevent import monkey;monkey.patch_all()
import gevent
import time
import requests
def func(url):
    res=requests.get(url)
    print(    url,res.status_code,len(res.text))

url_list=['http://www.sohu.com',
    'http://www.baidu.com',
    'http://www.qq.com',
    'http://www.python.org',
    'http://www.cnblogs.com',
    'http://www.mi.com',
    'http://www.apache.org',
    'https://www.taobao.com',
    'http://www.360.com',
    'http://www.7daysinn.cn/'
]

start=time.time()
for i in url_list:
    func(i)
print(time.time()-start)

def fu(url):
    res = requests.get(url)
    print(url,res.status_code,len(res.text))

url_lst =[
    'http://www.sohu.com',
    'http://www.baidu.com',
    'http://www.qq.com',
    'http://www.python.org',
    'http://www.cnblogs.com',
    'http://www.mi.com',
    'http://www.apache.org',
    'https://www.taobao.com',
    'http://www.360.com',
    'http://www.7daysinn.cn/'
]

g_lst = []
start = time.time()
for url in url_lst:
    g_lst.append(gevent.spawn(fu,url))
gevent.joinall(g_lst)
print(time.time() - start)
C:\Users\hc\AppData\Local\Programs\Python\Python36\python3.exe C:/s9/day40/40.py
http://www.sohu.com 200 186438
http://www.baidu.com 200 2381
http://www.qq.com 200 247169
http://www.python.org 200 48860
http://www.cnblogs.com 200 40834
http://www.mi.com 200 320204
http://www.apache.org 200 60819
https://www.taobao.com 200 125172
http://www.360.com 200 152637
http://www.7daysinn.cn/ 200 29467
4.937240123748779
http://www.mi.com 200 798
http://www.baidu.com 200 2381
http://www.sohu.com 200 186438
http://www.7daysinn.cn/ 200 29467
https://www.taobao.com 200 125172
http://www.qq.com 200 247173
http://www.360.com 200 152637
http://www.cnblogs.com 200 40834
http://www.apache.org 200 60819
http://www.python.org 200 48860
1.7020213603973389

Process finished with exit code 0

 

posted @ 2018-02-08 16:51  许光宗  阅读(150)  评论(0编辑  收藏  举报