python网络爬虫(第六章:协程的实现方法)

1.协程

协程(Coroutine):又称微线程,是一种用户态内的上下文切换技术。简而言之,就是通过一个线程实现代码块相互切换执行。

意义:在一个县城中如果遇到IO等待时间,线程不会傻傻等,会在空闲的时间再干其他事情。

一个线程,可以认为是人为的控制线程在函数之间进行线程切换,且仅有一个线程来完成切换。

实现协程的方法

1.greenlet 早期模块
2.yield关键字  yield是python中的生成器
3.asyncio装饰器(py3.4)
4.async、await关键字(py3.5)【推荐】

1.1greenlet实现协程

安装:

pip install greenlet

# 1. greenlet实现协程

from greenlet import greenlet

def func1():
    print(1)    #第二步:输出1
    gr2.swith()     #第三步:切换到func2函数
    print(2)    #第六步:输出2

def func2():
    print(3)    #第四步:输出3
    gr1.switch()    #第五步:切换到func1函数
    print(4)    #第七步:输出4

gr1 = greenlet(func1())
gr2 = greenlet(func2())

gr1.switch()    #第一步:执行func1函数

1.2 yield关键字实现协程

# 2. yield关键字 实现协程

def func1():    #如果一个函数中,存在yield关键字,则认为是一个生成器,则执行该函数,就生成一个生成器
    yield 1     #第二步:输出1
    yield from func2()  #第三步:表示跳到func2函数中
    yield 2     #第六步:输出2

def func2():
    yield 3     #第四步:输出3
    yield 4     #第五步:输出4

f1 = func1()
for item in f1:
    print(item) #第一步:执行func1函数

1.3 asyncio 实现协程

# 3. asyncio 实现协程【无需安装,但要求python需3.4及以上版本】
# 注意:遇到IO阻塞自动切换

import asyncio

@asyncio.coroutine
def func1():    #func1位普通函数,添加了asynic.coroutine装饰器后,则认为该函数为协程函数
    print(1)
    yield  from asyncio.sleep(2)  # 遇到IO耗时操作,自动切换到tasks中的其他任务
    print(2)

@asyncio.coroutine
def func2():
    print(3)
    yield  from asyncio.sleep(2)    # 遇到IO耗时操作,自动切换到tasks中的其他任务
    print(4)

#协程函数的执行, 则无法使用func1()方法进行执行,需要以下的方法进行执行
# loop = asyncio.get_event_loop()
# loop.run_until_complete(函数名称)  #使用以上代码,执行函数的协程操作 如:loop.run_until_complete(func())


#对func1和func2函数进行封装, 然后使用下面的4句代码,在pyhton内部,同时会执行这两个协程函数,线程会随机执行所有函数中的一个
tasks = [
    asyncio.ensure_future(func1()),
    asyncio.ensure_future(func2())
]

# 线程函数会随机执行func1和func2协程函数
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

假设首先执行func1函数,则在遇到 yield from asyncio.sleep(2),线程会跳转到其他协程函数中,但因为该python文件中仅有2个协程函数,
#因此,跳转执行func2函数,而在func2函数中遇到yield from asyncio.sleep(2),就又会跳转到func1函数冲,输出2,最后再到func2函数中,输出4.结束本次操作
#本代码输出结果为: 1 3 2 4

1.4 asyn &await 实现协程

# 4. async & await关键字【推荐】  在python3.5及以上


import asyncio


async def func1():    #func1位普通函数,添加了asynic.coroutine装饰器后,则认为该函数为协程函数
        print(1)
        await asyncio.sleep(2)  # 遇到IO耗时操作,自动切换到tasks中的其他任务
        print(2)

@asyncio.coroutine
async def func2():
        print(3)
        await asyncio.sleep(2)    # 遇到IO耗时操作,自动切换到tasks中的其他任务
        print(4)


#对func1和func2函数进行封装, 然后使用下面的4句代码,在pyhton内部,同时会执行这两个协程函数,线程会随机执行所有函数中的一个
tasks = [
    asyncio.ensure_future(func1()),
    asyncio.ensure_future(func2())
]

# 线程函数会随机执行func1和func2协程函数
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))

#说明:asyncio和 async & await区别不大,只是将@asyncio.coroutine替换为 asyn ;将yield from 替成 await,其他的都没变

上一篇:global、nonlocal


下一篇:C++11笔记-多线程-async()和Future