我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Python与协程从Python2—Py

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Python与协程从Python2—Py

Python与协程从Python2—Python3

协程,又称微线程、纤程,英文名Coroutine;用一句话说明什么是线程的话:协程是一种用户态的轻量级线程。

Python对于协程的支持在python2中还比较简单,但是也有可以使用的第三方库,在python3中开始全面支持,也成为python3的一个核心功能,很值得学习。

协程,又称微线程、纤程,英文名Coroutine;用一句话说明什么是线程的话:协程是一种用户态的轻量级线程。

协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。

协程的优点:

1)无需线程上下文切换的开销

2)无需原子操作锁定及同步的开销

3)方便切换控制流,简化编程模型

4)高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。

协程的缺点:

1)无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上

2)进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序

yield关键字
Python2对于协程的支持,是通过yield关键字实现的,下面示例代码是一个常见的生产者—消费者模型,代码示例如下:

def consumer():

    r = ''

    while True:

        n = yield r

        if not n:

            continue

        print('[CONSUMER] Consuming %s...' % n)

        r = '200 OK'

def produce(c):

    c.next()

    n = 0

    while n < 5:

        n = n + 1

        print('[PRODUCER] Producing %s...' % n)

        r = c.send(n)

        print('[PRODUCER] Consumer return: %s' % r)

    c.close()

if __name__ == '__main__':

    c = consumer()

    produce(c)

执行结果:

Python与协程从Python2—Python3

注意到consumer函数是一个generator(生成器),把一个consumer传入produce后:

1)首先调用c.next()启动生成器;

2)然后,一旦生产了东西,通过c.send(n)切换到consumer执行;

3)consumer通过yield拿到消息,处理,又通过yield把结果传回;

4)produce拿到consumer处理的结果,继续生产下一条消息;

5)produce决定不生产了,通过c.close()关闭consumer,整个过程结束。

整个流程无锁,由一个线程执行,produce和consumer协作完成任务,所以称为“协程”,而非线程的抢占式多任务。

传统的生产者-消费者模型是一个线程写消息,一个线程取消息,通过锁机制控制队列和等待,但一不小心就可能死锁。

如果改用协程,生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产,效率极高。

Python对协程的支持还非常有限,用在generator中的yield可以一定程度上实现协程。虽然支持不完全,但已经可以发挥相当大的威力了。

gevent模块
Python通过yield提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。gevent是第三方库,通过greenlet实现协程,其基本思想是:

当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成。

示例代码如下:


from gevent import monkey; monkey.patch_all()

import gevent

import urllib2

def f(url):

    print('GET: %s' % url)

    resp = urllib2.urlopen(url)

    data = resp.read()

    print('%d bytes received from %s.' % (len(data), url))

gevent.joinall([

        gevent.spawn(f, 'https://www.python.org/'),

        gevent.spawn(f, 'https://www.yahoo.com/'),

        gevent.spawn(f, 'https://github.com/'),

])

执行结果:
Python与协程从Python2—Python3

从执行结果可以看到,网站访问的顺序是自动切换的。

gevent优缺
使用gevent,可以获得极高的并发性能,但gevent只能在Unix/Linux下运行,在Windows下不保证正常安装和运行。Python创始人Gvanrossum从来不喜欢Gevent,而是更愿意另辟蹊径的实现asyncio(python3中的异步实现)。

1)Monkey-patching。中文「猴子补丁」,常用于对测试环境做一些hack。Gvanrossum说用它就是”patch-and-pray”,由于Gevent直接修改标准库里面大部分的阻塞式系统调用,包括socket、ssl、threading和 select等模块,而变为协作式运行。但是无法保证在复杂的生产环境中有哪些地方使用这些标准库会由于打了补丁而出现奇怪的问题,那么只能祈祷(pray)了。

2)其次,在Python之禅中明确说过:「Explicit is better than implicit.」,猴子补丁明显的背离了这个原则。

3)第三方库支持。得确保项目中用到其他用到的网络库也必须使用纯Python或者明确说明支持Gevent,而且就算有这样的第三方库,也需要担心这个第三方库的代码质量和功能性。

4)Greenlet不支持Jython和IronPython,这样就无法把gevent设计成一个标准库了。

之前是没有选择,很多人选择了Gevent,而现在明确的有了更正统的、正确的选择:asyncio(下一节会介绍)。所以建议大家了解Gevent,拥抱asyncio。

另外,如果知道现在以及未来使用Gevent不会给项目造成困扰,那么用Gevent也是可以的。

Gvanrossum希望在Python 3 实现一个原生的基于生成器的协程库,其中直接内置了对异步IO的支持,这就是asyncio,它在Python 3.4被引入到标准库。

下面将简单介绍asyncio的使用:

1)event_loop 事件循环:程序开启一个无限的循环,程序员会把一些函数注册到事件循环上。当满足事件发生的时候,调用相应的协程函数。

2)coroutine 协程:协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象。协程对象需要注册到事件循环,由事件循环调用。

3)task 任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含任务的各种状态。

4)future: 代表将来执行或没有执行的任务的结果。它和task上没有本质的区别

5)async/await 关键字:python3.5 用于定义协程的关键字,async定义一个协程,await用于挂起阻塞的异步调用接口。

代码示例如下:

import asyncio

import time

now = lambda: time.time()

async def do_some_work(x):

    print('Waiting: {}s'.format(x))

    await asyncio.sleep(x)

    return 'Done after {}s'.format(x)

async def main():

    coroutine1 = do_some_work(1)

    coroutine2 = do_some_work(5)

    coroutine3 = do_some_work(3)

    tasks = [

        asyncio.ensure_future(coroutine1),

        asyncio.ensure_future(coroutine2),

        asyncio.ensure_future(coroutine3)

    ]

    done, pending = await asyncio.wait(tasks)

    for task in done:

        print('Task ret: ', task.result())

start = now()

loop = asyncio.get_event_loop()

task = asyncio.ensure_future(main())

try:

    loop.run_until_complete(task)

    print('TIME: ', now() - start)

except KeyboardInterrupt as e:

    print(asyncio.Task.all_tasks())

    print(asyncio.gather(*asyncio.Task.all_tasks()).cancel())

    loop.stop()

    loop.run_forever()

finally:

    loop.close()

执行结果:
Python与协程从Python2—Python3

可以看到程序执行时间是以等待时间最长的为准。

使用async可以定义协程对象,使用await可以针对耗时的操作进行挂起,就像生成器里的yield一样,函数让出控制权。协程遇到await,事件循环将会挂起该协程,执行别的协程,直到其他的协程也挂起或者执行完毕,再进行下一个协程的执行。耗时的操作一般是一些IO操作,例如网络请求,文件读取等。我们使用asyncio.sleep函数来模拟IO操作。协程的目的也是让这些IO操作异步化。

Asyncio是python3中一个强大的内置库,上述只是简单的介绍了asyncio的用法有兴趣的话,很值得去学习一下!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Python与协程从Python2—Py

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python与协程从Python2—Py

协程,又称微线程、纤程,英文名Coroutine;用一句话说明什么是线程的话:协程是一种用户态的轻量级线程。Python对于协程的支持在python2中还比较简单,但是也有可以使用的第三方库,在python3中开始全面支持,也成为pytho
2023-01-31

【python】--python2与py

python3 和python 2 共存1.安装基础的系统包(因为我是在docker下启动的Linux, p_w_picpath中很多包没有装)yum install -y hostname  wget  tar passwd gcc lr
2023-01-31

python协程与golang协程的区

进程、线程和协程进程的定义:进程,是计算机中已运行程序的实体。程序本身只是指令、数据及其组织形式的描述,进程才是程序的真正运行实例。线程的定义:操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。进程和线程的关系
2023-01-31

Python:线程、进程与协程(6)——

上篇博文介绍了multiprocessing模块的内存共享(点击此处可以参看),下面讲进程池。有些情况下,所要完成的工作可以上篇博文介绍了multiprocessing模块的内存共享,下面讲进程池。有些情况下,所要完成的工作可以分解并独立地
2023-01-31

Python:线程、进程与协程(1)——

最近的业余时间主要放在了学习Python线程、进程和协程里,第一次用python的多线程和多进程是在两个月前,当时只是简单的看了几篇博文然后就跟着用,没有仔细去研究,第一次用的感觉它们其实挺简单的,最近这段时间通过看书, 看Python 中
2023-01-31

Python:线程、进程与协程(2)—

上一篇博文介绍了Python中线程、进程与协程的基本概念,通过这几天的学习总结,下面来讲讲Python的threading模块。首先来看看threading模块有哪些方法和类吧。主要有:Thread :线程类,这是用的最多的一个类,可以指定
2023-01-31

【PYTHON模块】:协程与greenl

协程:又称为微线程,英文名称Coroutine。作用:它拥有自己的寄存器上下文和栈,能保留上一次调用时的状态,可以随时暂停程序,随时切换回来。优点:    •无需线程上下文切换的开销    •无需原子操作锁定及同步的开销      •方便切
2023-01-31

Python:线程、进程与协程(3)——

Queue模块是提供队列操作的模块,队列是线程间最常用的交换数据的形式。该模块提供了三种队列:Queue.Queue(maxsize):先进先出,maxsize是队列的大小,其值为非正数时为无线循环队列Queue.LifoQueue(max
2023-01-31

Python:线程、进程与协程(7)——

前面转载了一篇分析进程池源码的博文,是一篇分析进程池很全面的文章,点击此处可以阅读。在Python中还有一个线程池的概念,它也有并发处理能力,在一定程度上能提高系统运行效率;不正之处欢迎批评指正。     线程的生命周期可以分为5个状态:创
2023-01-31

Python编程入门与实践 流畅的py

Python编程入门与实践针对零基础,即从来没有学过编程的朋友,应该作为入门上手的Python资料;分两部分:第一部分介绍用Python 编程所必须了解的基本概念,包括matplotlib、NumPy 和Pygal 等强大的Python 库
2023-01-31

python协程与asyncio库怎么用

今天小编给大家分享一下python协程与asyncio库怎么用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。1.asynci
2023-06-30

python中强制关闭线程、协程与进程的方法是什么

这篇“python中强制关闭线程、协程与进程的方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“python中强制关闭
2023-07-05

Python Django 协程报错,进程池、线程池与异步调用、回调机制

在Django视图函数中,导入gevent模块importgeventfromgeventimportmonkey;monkey.patch_all()fromgevent.poolimportPool启动Django报错:MonkeyPa
2023-01-31

Python并发编程中的线程通信,探索线程间的数据交换与协作

在Python并发编程中,线程间的数据交换和协作是实现任务并行、提高程序效率的关键。本文将探讨Python中线程通信的常用方法和技巧,帮助您深入理解线程间的协作机制,优化程序性能。
Python并发编程中的线程通信,探索线程间的数据交换与协作
2024-02-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录