python 线程进程协程(三)

1.在python3.4之前,协程是通过生成器(yield)实现的:

def count_down(n):
    while n > 0:
        yield n
        n -= 1


if __name__ == '__main__':
    rest = count_down(5)
    print(next(rest))
    print(next(rest))
    print(next(rest))
    print(next(rest))
    print(next(rest))

控制台输出:

5
4
3
2
1

或者将yield当成是一个赋值语句,实现协程的函数

def test_yield():

    while True:
        n = (yield)
        print(n)


if __name__ == '__main__':
    rest = test_yield()
    next(rest)
    rest.send('666')
    rest.send('666')

控制台输出:

666
666

2.python3.4之后,使用async和await关键字实现
使用async定义特殊的函数,当被调用时,不执行里面的代码,而是返回一个协程对象,在事件循环中调用执行代码前,协程对象不执行任何操作,因此,要先定义一个事件循环队列,并注册任务,即添加进事件队列,然后等待队列前面的任务执行结束,调用该任务,执行
当遇到阻塞调用的函数时,用await函数将协程的控制权让出,队列先调用其他的任务

import asyncio


async def do_sth(x):
    print('等待中:{0}'.format(x))
    await asyncio.sleep(x)

print(asyncio.iscoroutinefunction(do_sth))

coroutine = do_sth(5)

# 事件循环队列
loop = asyncio.get_event_loop()
# 注册任务
task = loop.create_task(coroutine)
print(task)
#执行直到结束
loop.run_until_complete(task)
print(task)

控制台输出:

True  # 是协程函数
<Task pending coro=<do_sth() running at D:/untitled/test_xiecheng/test.py:4>>
等待中:5
<Task finished coro=<do_sth() done, defined at D:/untitled/test_xiecheng/test.py:4> result=None>

3.协程通信之嵌套调用:
一个协程的执行过程,依赖于另一个协程函数的返回

import asyncio


async def comput(x, y):
    print('正在计算x+y==>{0}+{1}'.format(x,y))
    await asyncio.sleep(2)  # asyncio的sleep返回的是一个协程对象
    return x+y


async def get_sum(x,y):
    rest = await comput(x,y)
    # rest = comput(x,y)
    # 假设comput是一个相对任务(用asyncio模块中的sleep来模拟),
    # 等待comput函数执行结束之后要得到结果。用上await即可
    print('{0}+{1}={2}'.format(x, y, rest))

loop = asyncio.get_event_loop()
loop.run_until_complete(get_sum(1, 2))
loop.close()

4.协程通信之队列

import asyncio
import random


async def add(q,name):
    for i in range(10):
        await asyncio.sleep(random.randint(1,3))
        await q.put(i)
        print('add:{0},q.size:{1}'.format(name,q.qsize()))


async def reduce(q,name):
    while True:
        await asyncio.sleep(random.randint(1, 5))
        await q.get()
        print('reduce:{0},q.size:{1}'.format(name,q.qsize()))

q = asyncio.Queue(maxsize=5)
a1 = add(q,'a1')
r = reduce(q,'r')
# 事件循环队列
loop = asyncio.get_event_loop()
# 注册任务
#执行直到结束
loop.run_until_complete(asyncio.gather(a1,r))
loop.close()

控制台部分输出:

add:a1,q.size:1
add:a1,q.size:2
reduce:r,q.size:1
add:a1,q.size:2
reduce:r,q.size:1

此时由于get相关代码等待的时间比put长一些,所以会存在add多个,才有一个get的操作

猜你喜欢

转载自blog.csdn.net/qq_43523725/article/details/108342831