Python学习之路- 爬虫 - IO

IO模型

  1. 同步IO与异步IO
  • 同步IO

    • 概念:导致请求进程阻塞的IO操作,直到IO操作任务完成
    • 类型:BIO、NIO、IO多路复用
      • BIO:阻塞IO,发完请求后,一直等着
      • NIO:非阻塞IO,可以发完请求后,立刻返回没数据;可以做其他的事情;过一段时间再去发请求(类似轮训),这样是非阻塞
      • IO多路复用:IO多路复用这种方式虽然用了两个系统调用,但是它可以让我们在一个线程中去监听多个fd。在前面的BIO中,我们作为一个服务器,要处理n个客户端连接的读写请求,为了不让一个客户端的处理阻塞其它客户端的响应,我们需要每个线程对应一个客户端连接
        • epoll,poll,select,kqueue等机制
  • 异步IO

    • 概念:不导致进程阻塞的IO操作
    • 类型:AIO
    • 需要操作系统支持,用的较多的还是 IO多路复用
  • 注意:

    • 同步IO与异步IO判断依据是,第二阶段,从内存态拷贝数据到用户进程时,是否会导致用户进程阻塞
    • BIO中socket直接进程等待(用户进程主动等待,井在拷贝时也等待)
    • NIO中将数据从内核空间拷贝到用户空间时阻塞(用户进程主动询问,并在拷贝时等待)
    • IO多路复用中select等函数为阻塞、拷贝数据时也阻塞(用户进程主动等待,并在拷贝时也等待)
    • AIO中从始至终用户进程都没有阻塞(用户进程是被动的)

read系统,分为两个阶段:等待数据就绪(步骤一/阶段一),把就绪的数据从内核空间拷贝到用户的进程空间(步骤二/阶段二) 先说结论:各种IO模型其实是根据它在上述两个阶段的不同表现(用户进程或者线程是否阻塞)来区分的!!! 在第一个阶段用户进程是否阻塞用来区分阻塞/非阻塞,在第二个阶段用户是否阻塞用来区分同步/异步!!! 一文带你区分阻塞、非阻塞、同步、异步IO

异步IO框架

  1. 异步库
    1. asyncio
  2. 分布式异步框架
    1. celery
asyncio
  • 内置对象
    • event loop事件循环对象,程序开启一个无限循环,把一些函数注册到事件循环上,当满足事件发生的时候,调用相应的写成函数
    • coroutine协程对象,async 关键字定义的函数,它的调用不会立即执行函数,而是返回一个协程对象,协程对象需要注册到事件循环,由事件循环调用
    • Task对象,相当于对协程对象的进一步封装,并设置了多种任务状态,便于管理
      • Pending
      • Running
      • Finished
      • Cacelled
    • Future对象,和task对象基本一致,Task是Future的子类
    • await 用于挂起阻塞的异步调用接口,交出cpu控制权。async定义一个协程
使用
1. async 定义协程函数:购买事件,返回的是一个协程处理函数
2. 调用协程函数获得协程对象
3. asyncio.get_event_loop() 获取默认的事件循环对象
4. 根据协程对象创建task对象:注册事件event
5. 设置回调函数,也就是 event——handle ,这一步可要可不要
6. loop.run_until_complete(task) 启动事件循环

  • 如果用协程,尽量不要有耗时多的操作,会影响执行效率;task的回调函数,也是放在主线程操作的,也不要有耗时操作
    • 如果有耗时操作,有耗时的 io 操作,要用 await 交出控制权,注册回 loop中,让他调度
    • 如果cpu密集型耗时,则需要将事件放入用线程池中操作
'''asyncio事件驱动使用'''

import asyncio
import time

now = lambda: time.time()

def event_handle(future):
    if (future):
        print("购买 '%s' 成功" % future.result())
    else:
        print('购买失败')

# 1. 定义协程函数:购买事件
async def buy(item):
    return item

start = now()

# 2. 调用协程函数获得协程对象
coroutine = buy('电脑')
# 3. 获取默认的事件循环对象
loop = asyncio.get_event_loop()
# 4. 根据协程对象创建task对象:注册事件event
task = loop.create_task(coroutine)
# task = asyncio.ensure_future(coroutine)
# task = asyncio.Task(coroutine)

# 5. 设置回调函数,也就是 event——handle
task.add_done_callback(event_handle)
print(task)

# 6. 启动事件循环
loop.run_until_complete(task)
print(task)
print('耗时:',now() - start)


  • 多个task
'''asyncio事件驱动使用'''

import asyncio
import time

now = lambda: time.time()

def event_handle(future):
    if (future):
        print("购买 '%s' 成功" % future.result())
    else:
        print('购买失败')

# 1. 定义协程函数:购买事件
async def buy(item):
    await asyncio.sleep(1) # 即使每次都 sleep 了 1s,整个执行结果,循环了3个task,结果还是执行了1s多,协程的优势 
    return item

start = now()

# 2. 调用协程函数获得协程对象
coroutine = buy('电脑')
# 3. 获取默认的事件循环对象
loop = asyncio.get_event_loop()
# 4. 根据协程对象创建task对象:注册事件event
tasks =[]
for i in ["电脑","手机","掌机"]:
    task = asyncio.ensure_future(buy(i))
    # 5. 设置回调函数,也就是 event——handle
    task.add_done_callback(event_handle)
    tasks.append(task)

# 6. 启动事件循环
loop.run_until_complete(asyncio.wait(tasks))
print(task)
print('耗时:',now() - start)


使用线程池操作Task
  • asyncio 有些模块不兼容,比如请求库 requests,这个时候,也可以用线程池
    • 定义buy函数,是普通函数,不是 async 协程函数
    • loop.run_in_executor 传入 None ,默认是一个线程;可以创建一个进程池操作
'''asyncio事件驱动使用'''

import asyncio
import time

now = lambda: time.time()

def event_handle(future):
    if (future):
        print("购买 '%s' 成功" % future.result())
    else:
        print('购买失败')

# 1. 定义函数
def buy(item):
    return item

start = now()

# 3. 获取默认的事件循环对象
loop = asyncio.get_event_loop()
# 4. 默认 buy 会在一个线程池中运行
future = loop.run_in_executor(None,buy,'电脑')

# 5. 设置回调函数,也就是 event——handle
future.add_done_callback(event_handle)

# 6. 启动事件循环
loop.run_until_complete(future)
print('耗时:',now() - start)


协程的嵌套
  1. 如果是定义多个协程函数,然后用asyncio.as_complete(tasks)执行
---------------------------END---------------------------

题外话

在这里插入图片描述

感兴趣的小伙伴,赠送全套Python学习资料,包含面试题、简历资料等具体看下方。

👉CSDN大礼包🎁:全网最全《Python学习资料》免费赠送🆓!(安全链接,放心点击)

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。

img

二、Python兼职渠道推荐*

学的同时助你创收,每天花1-2小时兼职,轻松稿定生活费.
在这里插入图片描述

三、最新Python学习笔记

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。

img

四、实战案例

纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

img

👉CSDN大礼包🎁:全网最全《Python学习资料》免费赠送🆓!(安全链接,放心点击)

若有侵权,请联系删除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值