博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python中IO多路复用、协程
阅读量:5975 次
发布时间:2019-06-20

本文共 3665 字,大约阅读时间需要 12 分钟。

一、IO多路复用

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

import socketdef 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\r\nhost:www.baidu.com\r\n\r\n" %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 greenletdef f1():    print(11)    gr2.switch()    print(22)    gr2.switch()def f2():    print(33)    gr1.switch()    print(44)#协程gr1gr1 = greenlet.greenlet(f1)#协程gr2gr2 = greenlet.greenlet(f2)gr1.switch()
View Code

  注:单纯用协程无用

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

import geventfrom gevent import monkeymonkey.patch_all()import requestsdef 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, deferfrom twisted.internet import reactordef 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

 

转载于:https://www.cnblogs.com/qq849784670/p/9641711.html

你可能感兴趣的文章
洛谷 P2486 BZOJ 2243 [SDOI2011]染色
查看>>
数值积分中的辛普森方法及其误差估计
查看>>
Web service (一) 原理和项目开发实战
查看>>
跑带宽度多少合适_跑步机选购跑带要多宽,你的身体早就告诉你了
查看>>
Javascript异步数据的同步处理方法
查看>>
iis6 zencart1.39 伪静态规则
查看>>
SQL Server代理(3/12):代理警报和操作员
查看>>
Linux备份ifcfg-eth0文件导致的网络故障问题
查看>>
2018年尾总结——稳中成长
查看>>
通过jsp请求Servlet来操作HBASE
查看>>
Shell编程基础
查看>>
Shell之Sed常用用法
查看>>
Centos下基于Hadoop安装Spark(分布式)
查看>>
mysql开启binlog
查看>>
设置Eclipse编码方式
查看>>
分布式系统唯一ID生成方案汇总【转】
查看>>
并查集hdu1232
查看>>
Mysql 监视工具
查看>>
Linux Namespace系列(09):利用Namespace创建一个简单可用的容器
查看>>
博客搬家了
查看>>