zoukankan      html  css  js  c++  java
  • 协程(效率最快、重点)--初识协程、gevent模块、协程爬虫、协程socket(一)

    https://www.cnblogs.com/post/readauth?url=/mys6/p/10803772.html
    初识协程
    # 进程 启动多个进程 进程之间是由操作系统负责调用(时间片切换,人眼看似同时运行)
    # 线程 启动多个线程 真正被CPU执行的最小单位实际是线程(也可形成看似同时运行并发效果,由于python语言中CPython无法多线程使用多CPU,
    但其他语言多线程可使用多CPU,所以PYTHON不适合计算类程序,因为计算需要用到CPU)
    # 开启一个线程 创建一个线程(一小块内存消耗》》寄存器 堆栈)
    # 关闭一个线程(也需小量内存开销)
    # 协程
    # 本质上是一个线程
    # 能够在多个任务之间(程序之间)切换来节省一些IO时间
    # 协程中任务之间的切换也消耗时间,但是开销要远远小于进程线程之间的切换
    # 实现并发的手段


    # 一个简单模拟协程概念(两个函数之间切换)
    # import time
    # def consumer():
    # while True:
    # x = yield(生成器)
    # time.sleep(1)
    # print('处理了数据 :',x)
    #
    # def producer():
    # c = consumer()
    # next(c)
    # for i in range(10):
    # time.sleep(1)
    # print('生产了数据 :',i)
    # c.send(i)
    #
    # producer()




    # 真正的协程模块就是使用greenlet完成的切换
    # from greenlet import greenlet
    # def eat():
    # print('eating start')
    # g2.switch()
    # print('eating end')
    # g2.switch()
    #
    # def play():
    # print('playing start')
    # g1.switch()
    # print('playing end')
    # g1 = greenlet(eat)
    # g2 = greenlet(play)
    # g1.switch()

     nginx负载均衡内部就用到协程(最大并发5W)


    协程和gevent模块

    协程规避IO的例子(充分利用IO操作等待时间),无需关系两个函数之间是怎么切换的

    gevent模块相当与操作系统对进程的之间的切换一样,gevent是起到对协程遇到IO操作切换

    进程是操作系统资源分配单位,线程是CPU最小的执行单位,那协程呢?(就是对线程之间切换操作)


    # from gevent import monkey;monkey.patch_all() #这里如果不导入这段,gevent是无法识别time.sleep(1)(可以识别gevent.sleep(1),但系统时间一般用time模板)
    # import time
    # import gevent
    # import threading
    # def eat():
    # print(threading.current_thread().getName()) 查看虚拟线程名》》协程名,两个协程
    # print(threading.current_thread()) 协程(虚拟线程)ID,不是线程ID号,虽然两个协程ID不一样,但他们是在同一线程里

    # print('eating start')
    # time.sleep(1)
    # print('eating end')
    #
    # def play():
    # print(threading.current_thread().getName())
    # print(threading.current_thread())
    # print('playing start')
    # time.sleep(1)
    # print('playing end')
    #
    # g1 = gevent.spawn(eat) # 开启一个协程
    # g2 = gevent.spawn(play)
    # g1.join()识别一个程序的结束
    # g2.join()

    # 进程和线程的任务切换右操作系统完成,不管进程或线程里代码写的什么,到了时间片轮换就切换,
    # 协程任务之间的切换由程序(代码)完成,只有遇到协程模块能识别的IO操作的时候,程序才会进行任务切换,实现并发的效果
    如果没遇到IO操作,就不会进行任务切换,不能实现并发的效果,而是按代码顺序执行







    
    


    # 同步 和 异步
    # from gevent import monkey;monkey.patch_all()
    # import time
    # import gevent
    #
    # def task(n):
    # time.sleep(1)
    # print(n)
    #
    # def sync(): # 同步方式
    # for i in range(10):
    # task(i)
    #
    # def async(): #异步方式,高网络IO情况使用这种协程方式比较好,小IO或计算类不适合用协程
    # g_lst = []
    # for i in range(10):
    # g = gevent.spawn(task,i)
    # g_lst.append(g)
    # gevent.joinall(g_lst) 传入一个可迭代对象 # 等同于for g in g_lst:g.join()的效果

    # sync()
    # async()


    # 协程 : 能够在一个线程中实现并发效果的概念
    # 能够规避一些任务中的IO操作
    # 在任务的执行过程中,检测到IO就切换到其他任务

    # 多线程 被弱化了
    # 协程 在一个线程上 提高CPU 的利用率
    # 协程相比于多线程的优势 切换的效率更快

    # 爬虫的例子(需要正则基础)
    # 请求过程中的IO等待


    # from gevent import monkey;monkey.patch_all() 捕获IO或网络延迟
    # import gevent
    # from urllib.request import urlopen # 内置的模块
    # def get_url(url):
    # response = urlopen(url)
    # content = response.read().decode('utf-8')
    # return len(content)
    #
    # g1 = gevent.spawn(get_url,'http://www.baidu.com')
    # g2 = gevent.spawn(get_url,'http://www.sogou.com')
    # g3 = gevent.spawn(get_url,'http://www.taobao.com')
    # g4 = gevent.spawn(get_url,'http://www.hao123.com')
    # g5 = gevent.spawn(get_url,'http://www.cnblogs.com')
    # gevent.joinall([g1,g2,g3,g4,g5]) 识别所有代码结束
    # print(g1.value)
    # print(g2.value)一起打印(并发效果)
    # print(g3.value)
    # print(g4.value)
    # print(g5.value)
    # ret = get_url('http://www.baidu.com')
    # print(ret)
    协程socket

    server端
    from gevent import monkey;monkey.patch_all()
    import socket
    import gevent
    def talk(conn):
    conn.send(b'hello')
    print(conn.recv(1024).decode('utf-8'))
    conn.close()

    sk = socket.socket() sk.bind(('127.0.0.1',8080))
    sk.listen()
    while True: #异步
    conn,addr = sk.accept()
    gevent.spawn(talk,conn)
    sk.close()


    client端
    import socket
    sk = socket.socket()
    sk.connect(('127.0.0.1',8080))
    print(sk.recv(1024))
    msg = input('>>>').encode('utf-8')
    sk.send(msg)
    sk.close()












  • 相关阅读:
    《Microsoft Sql server 2008 Internals》读书笔记第六章Indexes:Internals and Management(4)
    《Microsoft Sql server 2008 Internals》读书笔记第六章Indexes:Internals and Management(9)
    《Microsoft Sql server 2008 Internals》读书笔记第六章Indexes:Internals and Management(3)
    《Microsoft Sql server 2008 Internals》读书笔记第六章Indexes:Internals and Management(5)
    《Microsoft Sql server 2008 Internals》读书笔记第六章Indexes:Internals and Management(7)
    vs2010正式版安装图解
    Winform部署mshtml程序集出错的一个解决方案
    InstallShield 2010集成.net Framework 4的安装包制作
    vs2010无法访问svn存储库的一次意外
    InstallShield集成.net Framework的安装包制作
  • 原文地址:https://www.cnblogs.com/mys6/p/10890083.html
Copyright © 2011-2022 走看看