协程

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

复制代码
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 @   许光宗  阅读(155)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示