美文网首页
知道了Python多线程和进程,你可能不知道协程的存在

知道了Python多线程和进程,你可能不知道协程的存在

作者: b8a7c7695f14 | 来源:发表于2020-04-09 12:29 被阅读0次
image

@Author: runsen

协程是实现并发编程的一种方式。

https://docs.python.org/zh-cn/3/library/asyncio.html

一说并发,你肯定想到了多线程 , 多进程模型,没错,多线程 和 多进程,正是解决并发问题的经典模型之一

但是你了解过协程Coroutine吗?

协程:是单线程下的并发,又称微线程。

就是只有一个线程,如何提高速度,解决并发编程

英文名Coroutine。

协程比线程的单位更小——协程

注意协程这个概念完全是程序员自己想出来的东西,它对于操作系统来说根本不存在。操作系统只有进程和线程。

从一个demo学起

import time 

def print_num(num):
    print("Maoli is printing " + str(num) + " nows" )
    time.sleep(1)
    print("Maoli prints" + str(num) + " OK")

def main(nums):
    for num in nums:
        print_num(num)
%time main([i for i in range(1,6)])


Maoli is printing 1 nows
Maoli prints1 OK
Maoli is printing 2 nows
Maoli prints2 OK
Maoli is printing 3 nows
Maoli prints3 OK
Maoli is printing 4 nows
Maoli prints4 OK
Maoli is printing 5 nows
Maoli prints5 OK
Wall time: 5 s

%time 需要在jupyter notebook中运行。

上面代码是从上到下执行的。

下面将上面代码改为协程版

注意py版本3.7以上,主要使用的是asyncio

import asyncio

async def print_num(num):
    print("Maoli is printing " + str(num) + " nows" )
    await asyncio.sleep(1)
    print("Maoli prints" + str(num) + " OK")

async def main(nums):
    for num in nums:
        await print_num(num)
%time asyncio.run(main([i for i in range(1,6)]))


Maoli is printing 1 nows
Maoli prints1 OK
Maoli is printing 2 nows
Maoli prints2 OK
Maoli is printing 3 nows
Maoli prints3 OK
Maoli is printing 4 nows
Maoli prints4 OK
Maoli is printing 5 nows
Maoli prints5 OK
Wall time: 5.01 s

asyncio.run() 函数用来运行最高层级的入口点 "main()" 函数

await 是同步调用等待一个协程。以下代码段会在等待 1 秒后打印 num,速度上没有发生改变。

需要引入asyncio.create_task才可以

可等待对象

如果一个对象可以在 await 语句中使用,那么它就是 可等待 对象

协程中的还一个重要概念,任务(Task)

如果写一个数字是一个任务,那么毛利我要完成5个任务

毛利我写个1-5都这么慢,不行,我要加速写

asyncio.create_task() 函数用来并发运行作为 asyncio 任务 的多个协程。

import asyncio

async def print_num(num):
    print("Maoli is printing " + str(num) + " nows" )
    await asyncio.sleep(1)
    print("Maoli prints" + str(num) + " OK")

async def main(nums):
    tasks = [asyncio.create_task(print_num(num)) for num in nums]
    for task in tasks:
        await task
%time asyncio.run(main([i for i in range(1,6)]))


Maoli is printing 1 nows
Maoli is printing 2 nows
Maoli is printing 3 nows
Maoli is printing 4 nows
Maoli is printing 5 nows
Maoli prints1 OK
Maoli prints3 OK
Maoli prints5 OK
Maoli prints2 OK
Maoli prints4 OK
Wall time: 1.01 s

还可以写成await asyncio.gather(*tasks)这种方法

import asyncio

async def print_num(num):
    print("Maoli is printing " + str(num) + " nows" )
    await asyncio.sleep(1)
    print("Maoli prints" + str(num) + " OK")

async def main(nums):
    tasks = [asyncio.create_task(print_num(num)) for num in nums]
    await asyncio.gather(*tasks)
%time asyncio.run(main([i for i in range(1,6)]))

*tasks 解包列表,将列表变成了函数的参数;与之对应的是, ** dict 将字典变成了函数的参数。

asyncio 队列

asyncio也是只有在Pytohn3.7才有的东西。

asyncio 队列被设计成与 queue 模块类似。

import asyncio
import random

async def consumer(queue, id):
    while True:
        val = await queue.get()
        print('{} get a val: {}'.format(id, val))
        await asyncio.sleep(1)

async def producer(queue, id):
    for i in range(5):
        val = random.randint(1, 10)
        await queue.put(val)
        print('{} put a val: {}'.format(id, val))
        await asyncio.sleep(1)

async def main():
    # 创建队列
    queue = asyncio.Queue()
    # 消费者1号
    consumer_1 = asyncio.create_task(consumer(queue, 'consumer_1'))
    # 消费者2号
    consumer_2 = asyncio.create_task(consumer(queue, 'consumer_2'))
    # 生产者1号
    producer_1 = asyncio.create_task(producer(queue, 'producer_1'))
    # 生产者2号
    producer_2 = asyncio.create_task(producer(queue, 'producer_2'))
    # stop 10秒
    await asyncio.sleep(10)
    consumer_1.cancel()
    consumer_2.cancel()
    
    await asyncio.gather(consumer_1, consumer_2, producer_1, producer_2, return_exceptions=True)

%time asyncio.run(main())

协程的写法简洁清晰,只要把 async / await 语法和 create_task 结合来用,就是Python中比较常见的协程

如果不会多线程,看我之前文章

相关文章

  • Gevent高并发网络库精解

    进程 线程 协程 异步 并发编程(不是并行)目前有四种方式:多进程、多线程、协程和异步。 多进程编程在python...

  • Python多进程(Multiprocessing)的简单使用

    Python由于GIL的存在,多线程(Thread)、协程(Asyncio)可以实现并发,并行则依赖多进程(Mul...

  • python多线程、多进程、协程的使用

    python多线程、多进程、协程的使用 本文主要介绍多线程、多进程、协程的最常见使用,每个的详细说明与介绍有时间会...

  • 索引 - Python

    文集主页 Python 解释器和三种栈多进程、多线程、协程、并发并行Python I/O 操作(一)Python ...

  • 知道了Python多线程和进程,你可能不知道协程的存在

    @Author: runsen 协程是实现并发编程的一种方式。 https://docs.python.org/z...

  • python常用知识

    多线程,多进程,协程进程池 协程 字典 列表 函数 文件操作

  • 浅析python的GIL

    Python中的GIL锁 在Python中,可以通过多进程、多线程和多协程来实现多任务。 在多线程的实现过程中,为...

  • Python3 异步协程函数async具体用法

    之前使用Python的人往往纠缠在多线程,多进程,评判哪个效率更高?其实,相对于别家的协程和异步,不管多线程还是多...

  • Gevent

    前述 进程 线程 协程 异步 并发编程(不是并行)目前有四种方式:多进程、多线程、协程和异步。 多进程编程在pyt...

  • Gevent简明教程

    前述 进程 线程 协程 异步 并发编程(不是并行)目前有四种方式:多进程、多线程、协程和异步。 多进程编程在pyt...

网友评论

      本文标题:知道了Python多线程和进程,你可能不知道协程的存在

      本文链接:https://www.haomeiwen.com/subject/kpzqmhtx.html