• python中IO多路复用、协程


    一、IO多路复用
        IO多路复用:检测多个socket是否已经发生变化(是否已经连接成功/是否已经获取数据)(可读/可写)

    import socket
    def get_data(key):
        client = socket.socket()
        client.setblocking(False)   #将原阻塞的位置变成非阻塞
        try:
            client.connect(("www.baidu.com",80))    #因为没有等待所以会报错
        except BlockingIOError as e:
            pass
        client.sendall(b"GET /s?wd=%s HTTP/1.0
    host:www.baidu.com
    
    " %key)
        data_list = []
        while 1:
            data = client.recv(8096)
            if not data:
                break
            data_list.append(data)
        data = b"".join(data_list)
        print(data.decode("utf8"))
    key_list = ["alex","sb","db"]
    for item in key_list:
        get_data(item)
    View Code

    二、基于IO多路复用+socket实现并发请求
      IO多路复用
      socket非阻塞
      基于事件循环实现的异步非阻塞框架
        非阻塞:不等待
        异步:执行完某个人物后自动调用我给他的函数。
          Python中开源 基于事件循环实现的异步非阻塞框架 Twisted

        总结:
          1. socket默认是否是阻塞的?阻塞体现在哪里?
              是,connect、accept、recv
          2. 如何让socket编程非阻塞?
              setblocking(False)
          3. IO多路复用作用?
            检测多个socket是否发生变化。
            操作系统检测socket是否发生变化,有三种模式:
              select:最多1024个socket;循环去检测。
              poll:不限制监听socket个数;循环去检测(水平触发)。
              epoll:不限制监听socket个数;回调方式(边缘触发)。
            Python模块:
              select.select
              select.epoll

          4. 提高并发方案:
            - 多进程
            - 多线程
            - 异步非阻塞模块(Twisted) scrapy框架(单线程完成并发)

          5. 什么是异步非阻塞?
            - 非阻塞,不等待。
              比如创建socket对某个地址进行connect、获取接收数据recv时默认都会等待(连接成功或接收到数据),才执行后续操作。
              如果设置setblocking(False),以上两个过程就不再等待,但是会报BlockingIOError的错误,只要捕获即可。
            - 异步,通知,执行完成之后自动执行回调函数或自动执行某些操作(通知)。

          6. 什么是同步阻塞?
            - 阻塞:等
            - 同步:按照顺序逐步执行
            key_list = ['alex','db','sb']
            for item in key_list:
              ret = requests.get('https://www.baidu.com/s?wd=%s' %item)
              print(ret.text)

          7.概念 

    #以前
    v = [[11,22],[33,44],[55,66]] #每一个都有一个append方法
    for item in v:
        print(item.append(1))
    #以后
    class Foo(object):
        def __init__(self,data):
            self.data = data
        def append(self,ietm):
            self.data.appded(item)
    v = [[11,22],[33,44],[55,66]]
    for item in v:
        print(item.append(1))
    面向对象的思想

    三、协程

        概念:

          进程、操作系统中存在

          线程、操作系统中存在

          协程、是由程序员创造出来的一个不是真实存在的东西

      协程:是微线程,是对一个线程进行分片,使得线程在代码块之间来回切回执行,而不是在原来逐行执行

    import greenlet
    def f1():
        print(11)
        gr2.switch()
        print(22)
        gr2.switch()
    def f2():
        print(33)
        gr1.switch()
        print(44)
    #协程gr1
    gr1 = greenlet.greenlet(f1)
    #协程gr2
    gr2 = greenlet.greenlet(f2)
    gr1.switch()
    View Code

      注:单纯用协程无用

      协程+遇到IO就切换,才真的有用  pip3 install gevent

    import gevent
    from gevent import monkey
    monkey.patch_all()
    import requests
    def get_page1(url):
        ret = requests.get(url)
        print(url,ret.content)
    def get_page2(url):
        ret = requests.get(url)
        print(url,ret.content)
    def get_page3(url):
        ret = requests.get(url)
        print(url,ret.content)
    gevent.joinall([gevent.spawn(get_page1, 'https://www.python.org/'),
                    gevent.spawn(get_page2, 'https://www.yahoo.com/'),
                    gevent.spawn(get_page3, 'https://github.com/')
                    ])
    View Code

      总结:

        1什么是协程:

          协程也可以成为微线程,基石开发者控制线程执行流程,控制先执行某段代码然后在切换到另外函数执行代码

        2.协程可以提高并发么

          协程自己本身无法实现并发(甚至性能会降低)

          协程+IO切换性能提高

        3.进程、线程、协程的区别

        4.单线程提高并发:

          协程+IO切换:gevent

          基于事件循环的异步非阻塞框架:Twisted

    twisted

    from twisted.web.client import getPage, defer
    from twisted.internet import reactor
    
    def all_done(arg):
        reactor.stop()
    
    def callback(contents):
        print(contents)
    
    deferred_list = []
    url_list = ['http://www.bing.com', 'http://www.baidu.com', ]
    for url in url_list:
        deferred = getPage(bytes(url, encoding='utf8'))
        deferred.addCallback(callback)
        deferred_list.append(deferred)
    
    dlist = defer.DeferredList(deferred_list)
    dlist.addBoth(all_done)
    
    reactor.run()
    View Code
  • 相关阅读:
    nfs-client-provisioner 利用NFS动态提供Kubernetes后端存储卷
    docker-compose简易编写和模板命令
    shell脚本自动过滤尝试多次连接ip并添加到系统黑名单
    Centos 升级glibc 亲测好用
    centos安装Jenkins报错
    centos8 安装docker启动失败
    cenots7 rpm 包升级ssh
    python备份文件(简易)
    Docker 容器基本操作(基础)
    Docker 环境下如何配置你的镜像(基础)
  • 原文地址:https://www.cnblogs.com/qq849784670/p/9641711.html
Copyright © 2020-2023  润新知