asyncio模块

import asyncio


# 标识是一个协程函数
async def demo():  # 协程方法
    print("start")
    await asyncio.sleep(1)  # 阻塞
    print("end")


# 第三方操作demo
loop = asyncio.get_event_loop()  # 创建一个事件循环
loop.run_until_complete(demo())  # 把demo任务放到事件循环中执行

# 结果:
  start
  end
import asyncio

# 启动多个任务,没有返回值

async def demo():
    print("start")
    await asyncio.sleep(1)
    print("end")


loop = asyncio.get_event_loop()
wait_obj = asyncio.wait([demo(), demo(), demo(), demo()])
loop.run_until_complete(wait_obj)

# 结果:
    start
    start
    start
    start
    end
    end
    end
    end
import asyncio

# 启动多个任务并且有返回值
async def demo():
    print("start")
    await asyncio.sleep(1)
    print("end")
    return 123


loop = asyncio.get_event_loop()
t1 = loop.create_task(demo())
t2 = loop.create_task(demo())
t3 = loop.create_task(demo())
tasks = [t1, t2, t3]
wait_obj = asyncio.wait([t1, t2])
loop.run_until_complete(wait_obj)
for t in tasks:print(t.result())

# 结果
    start
    start
    start
    end
    end
    end
    123
    123
    123
import asyncio

# 谁先回来先取谁的结果
async def demo(i):
    print("start")
    await asyncio.sleep(10 - i)
    print("end")
    return i, 123


async def main():
    task_l = []
    for i in range(10):
        task = asyncio.ensure_future(demo(i))
        task_l.append(task)
    for ret in asyncio.as_completed(task_l):
        res = await ret
        print(res)


loop = asyncio.get_event_loop()
loop.run_until_complete(main())

# 结果:
    start
    start
    start
    start
    start
    start
    start
    start
    start
    start
    end
    (9, 123)
    end
    (8, 123)
    end
    (7, 123)
    end
    (6, 123)
    end
    (5, 123)
    end
    (4, 123)
    end
    (3, 123)
    end
    (2, 123)
    end
    (1, 123)
    end
    (0, 123)

总结:

# await 后面跟阻塞事件,协程函数从这里要切换出去,还能保证一会切回来
# await 必须写在async函数里,async函数是协程函数(类似生成器)
# loop 是一个事件循环
# 所有的协程执行,调度都离不开loop

单线程+多任务异步协程

- 意义:提升爬取数据的效率

- 实现异步爬虫的方式:

  - 多线程/多进程(不建议)

  - 线程池(可适当使用)

  - 单线程+多任务异步协程(推荐使用)

- 概念

  - 协程:协程对象。

   - 可以使用async关键字修饰的一个函数的定义(特殊的函数),当该函数被调用后,就可以返回一个协程对象。

   ( 当函数调用后,函数内部的实现语句不会被立即执行。)

  - 任务对象:

    - 本质上就是对协程对象的进一步封装。

    - 可以给任务对象绑定一个回调

      - add_done_callback(callback)

  - 事件循环(EventLoop):无限的循环对象

    - 我们必须将任务对象注册到事件循环对象中,然后开启事件循环对象。

    - 事件循环对象在执行任务对象的时候是基于异步的。

  - await async

  - 注意事项:

    - 保证特殊函数内部不可以出现不支持异步模块对应的代码

    - 在特殊函数内部遇到阻塞操作必须使用await关键字对其进行手动挂起

    - 如果想要将多个任务对象注册到事件循环中,必须将多个任务对象封装到一个列表中,然后将列表注册到事件循环中(也必须使用await方法将列表中的任务对象进行挂起)

 

import asyncio

# 定义一个特殊的函数
async def test(num):
    print(num)


# 返回一个协程对象,并且函数内部的语句不会立即执行
c = test(10)
print(c)
'''

'''
async def test(num):
    print(num)


c = test(10)

# 根据协程对象封装一个任务对象
task = asyncio.ensure_future(c)
print(task)
import asyncio
import time

async def request(url):
    print("正在请求:", url)
    time.sleep(2)
    print("请求完毕!", url)


c1 = request("www.baidu.com")

task_A = asyncio.ensure_future(c1)

# 创建一个事件循环对象
loop = asyncio.get_event_loop()
# 将任务对象注册到该对象中并且启动事件循环
loop.run_until_complete(task_A)

import asyncio
import time


async def request(url):
    print('正在请求:', url)
    time.sleep(2)
    print("请求完毕!", url)

    return url


# 定义一个任务对象的回调函数
# task参数表示的就是该函数被绑定的那个任务对象
def task_callback(task):
    print("i am task_callback()")
    print(task.result())
    # task.result()返回的就是任务对象对应的特殊函数内部的返回值


c = request("www.xxx.com")

task = asyncio.ensure_future(c)
task.add_done_callback(task_callback)

loop = asyncio.get_event_loop()
loop.run_until_complete(task)

任务对象绑定回调