1-Python - asyncio

about

asyncio是Python原生的底层协程模块。
应用于爬虫和webserver框架的底层。
asyncio有所了解,有助于加深对协程的理解。

开启一个协程任务

import asyncio


async def func():   # 协程函数
    print('start...')
    await asyncio.sleep(1)  # 阻塞
    print('end....')


loop = asyncio.get_event_loop()   # 开启事件循环
loop.run_until_complete(func())

上例是使用asyncio实现协程任务的标准示例。
需要补充的是:

  • async声明一个协程函数。
  • await是其阻塞作用,协程函数要从这里切换出去,还能保证再切回来。另外,await必须写在async函数中。
  • loop是事件循环,所有的协程的执行、调度都离不开这个loop

开启多个协程任务

启动多个任务,无返回值

import asyncio


async def func():
    print('start...')
    await asyncio.sleep(1)
    print('end....')


loop = asyncio.get_event_loop()
waite_obj = asyncio.wait([func(), func(), func(), func(), func()])
loop.run_until_complete(waite_obj)

'''
start...
start...
start...
start...
start...
end....
end....
end....
end....
end....
'''

上例是使用asyncio实现多个协程任务的示例。
启动多个任务,无返回值

import asyncio


async def func():
    print('start...')
    await asyncio.sleep(1)
    print('end....')
    return 123


# 写法1
loop = asyncio.get_event_loop()
t1 = loop.create_task(func())
t2 = loop.create_task(func())
waite_obj = asyncio.wait([t1, t2])
loop.run_until_complete(waite_obj)

print(t1.result())
print(t2.result())
'''
start...
start...
end....
end....
123
123
'''

# 写法2
# loop = asyncio.get_event_loop()
# task_list = [loop.create_task(func()) for i in range(5)]
# waite_obj = asyncio.wait(task_list)
# loop.run_until_complete(waite_obj)
#
# for i in task_list:
#     print(i.result())
'''
start...
start...
start...
start...
start...
end....
end....
end....
end....
end....
123
123
123
123
123
'''

上面的执行顺序虽然是并发,但也是按照任务启动的顺序来执行的。
下面的示例是协程实现并发,且谁先执行完谁返回:

import asyncio
from bs4 import BeautifulSoup

async def func(i):
    reader, writer = await asyncio.open_connection('www.baidu.com', 80)
    writer.write(b'GET / HTTP/1.1\r\nHOST:www.baidu.com\r\nConnection:close\r\n\r\n')
    html = ''
    async for line in reader:
        html += line.decode() + '\n'

    soup = BeautifulSoup(html, 'html.parser')
    title = soup.find(name='title').text
    return title, 'task num: {}'.format(i)


async def main():
    task_list = []
    for i in range(1, 11):
        task = asyncio.ensure_future(func(i))
        task_list.append(task)

    for result in asyncio.as_completed(task_list):
        result = await result
        print(result)

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

"""
('百度一下,你就知道', 'task num: 1')
('百度一下,你就知道', 'task num: 3')
('百度一下,你就知道', 'task num: 4')
('百度一下,你就知道', 'task num: 2')
('百度一下,你就知道', 'task num: 6')
('百度一下,你就知道', 'task num: 5')
('百度一下,你就知道', 'task num: 10')
('百度一下,你就知道', 'task num: 8')
('百度一下,你就知道', 'task num: 7')
('百度一下,你就知道', 'task num: 9')
"""

虽然实现了,谁先完事儿谁返回的效果,但很明显,你要直接用asyncio来搞爬虫,那肯定要劝退了,因为自己实现太麻烦了,也太难了!所以,这里只是演示使用asyncio来实现爬虫,但真正的写并发爬虫都是用别的模块,比如使用aiohttp模块,它封装了asyncio,也封装了http相关模块。


that's all
posted @ 2020-12-16 10:21  听雨危楼  阅读(217)  评论(0编辑  收藏  举报