美文网首页
python协程

python协程

作者: 清水秋香 | 来源:发表于2020-03-23 17:21 被阅读0次

    协程本质上是单任务,协程依赖于线程
    携程相对于线程来讲占用的资源更少(几乎不占什么资源)

    • 通过生成器,来实现协程
    import time
    
    def work1():
        for i in range(10):
            print('work1--{}'.format(i))
            time.sleep(0.1)
            yield
    
    
    
    def work2():
        for i in range(10):
            print('work2----{}'.format(i))
            time.sleep(0.1)
            yield
    
    #通过生成器实现多任务
    g1 = work1()
    g2 = work2()
    while True:
        try:
            next(g1)
            next(g2)
        except StopIteration:
            break
    

    greenlet对yield进行了进一步封装(了解即可)

    import time
    from greenlet import greenlet
    
    def work1():
        for i in range(10):
            print('work1--{}'.format(i))
            g2.switch()
            time.sleep(0.1)
    
    
    
    
    def work2():
        for i in range(10):
            print('work2----{}'.format(i))
            g1.switch()
            time.sleep(0.1)
    g1 = greenlet(work1)
    g2 = greenlet(work2)
    g1.switch()
    g2.switch()
    

    协程:gevent
    协程存在于线程之中,线程默认不会等待协程执行

    • spawn:开启协程(第一个参数为协程要执行的任务)
    • join:让线程等待协程执行
      协程之间切换的条件
    • gevent.sleep() 协程耗时等待的情况下才会切换
    • gevent.monkey.path_all() gevent程序补丁 不需要用gevent.sleep(),只要耗时就会切换到其他协程里面

    并发首先考虑 协程 > 线程 > 进程 进程资源占用太大

    import gevent
    import time
    from gevent import monkey
    import requests
    monkey.patch_all()
    from  queue import Queue
    q = Queue()
    for i in range(1000):
        q.put('http://www.baidu.com')
    
    def work():
        while q.qsize() > 0:
            url = q.get()
            requests.get(url)
    
    st = time.time()
    g1 = gevent.spawn(work)
    g2 = gevent.spawn(work)
    g3 = gevent.spawn(work)
    g4 = gevent.spawn(work)
    g5 = gevent.spawn(work)
    g1.join()
    g2.join()#耗时19.744673013687134
    g3.join()#耗时15.10847282409668
    g4.join()
    g5.join()#耗时12.241680145263672
    # work() #耗时38.67655611038208
    et = time.time()
    print('耗时{}'.format(et-st))
    #io耗时操作比较多协程节约的时间越多
    
    • 10000个请求,使用开启2个进程,进程中开启3线程,线程中开启5个协程来处理
      (30个协程)
    # -*- coding: utf-8 -*-
    
    import time
    from threading import Thread
    from multiprocessing import Process,Queue
    import gevent
    import requests
    
    #requests.get('https://www.apple.com/') 如果是mac用户需要打开此条注释,否则网络请求不会执行。
    
    def process_work(q,pname):
    
        '''
        每个进程执行的任务函数,在该进程中开启3个线程
        创建三个线程
        :param q: 进程间通讯的任务队列
        :param pname: 进程的名字
        :return:
        '''
        thread_list = []
        for i in range(3):
            tname = "{}-th-{}".format(pname,i)
            print('创建线程{}'.format(tname))
            t= Thread(target=thread_work,args=(q,tname))
            thread_list.append(t)
            t.start()
        for t in thread_list:
            t.join()
    def thread_work(q,tname):
    
        '''
        每个线程的执行任务函数,在该线程中开启5个协程
        :return:
        '''
        g_list = []
        for i in range(5):
            gname = '{}-g-{}'.format(tname,i)
            print('创建协程-----{}'.format(gname))
            g = gevent.spawn(green_work,q,gname)
            g_list.append(g)
        print('---------------------',len(g_list))
        for i in g_list:
            i.join()
    
    
    def green_work(q,gname):
    
        count = 0
        while not q.empty():
            url = q.get(timeout=0.01)
            # print(url)
            requests.get(url)
            gevent.sleep(0.001)
            count += 1
        print('----------协程{}执行了{}个任务'.format(gname,count))
    
    
    
    def count_time(func):
    
        def wrapper(*args,**kwargs):
            print('开始执行')
            start_time = time.time()
            func(*args,**kwargs)
            end_time = time.time()
            print('执行结束')
            print('总耗时:{}'.format(end_time-start_time))
        return wrapper
    
    @count_time
    def main():
        q = Queue()
        for i in range(1000):
            q.put('https://www.apple.com/')
        print('队列为空吗',q.empty())
        pro_list = []
        for i in range(2):
            pname = 'pro-{}'.format(i)
            print('创建进程{}'.format(pname))
            p = Process(target=process_work,args=(q,pname))
            p.start()
            pro_list.append(p)
        for p in pro_list:
            p.join()
    if __name__ == '__main__':
        main()
    
    

    相关文章

      网友评论

          本文标题:python协程

          本文链接:https://www.haomeiwen.com/subject/avnwyhtx.html