python协程

简介:

基础

http://yeqianfeng.me/python-yield-expression/

国外写的通俗易懂的

http://www.dabeaz.com/coroutines/index.html


协程的好处,处理io有优势。

gevent实现协程案例

多进程+协程下,避开了CPU切换的开销,又能把多个CPU充分利用起来,这种方式对于数据量较大的爬虫还有文件读写之类的效率提升是巨大的。


多进程+协程的问题,是怎么控制进程池的问题,可以看看gevent.pool这个协程池


当我们面对如下的环境时,事件驱动模型通常是一个好的选择:


程序中有许多任务,而且…

任务之间高度独立(因此它们不需要互相通信,或者等待彼此)而且…

在等待事件到来时,某些任务会阻塞。

当应用程序需要在任务间共享可变的数据时,这也是一个不错的选择,因为这里不需要采用同步处理。


网络应用程序通常都有上述这些特点,这使得它们能够很好的契合事件驱动编程模型。



协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:


协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。


协程,使用它之前我们先讲讲what/why/how(它是什么/为什么用它/怎么使用它)



基本认识

代码

总结



计算机分为IO bound 和CPU bound两种类型的task


基本认识

参考 http://blog.csdn.net/u014745194/article/details/71657575

Coroutine

协程其实可以认为是比线程更小的执行单元。 为啥说他是一个执行单元,因为他自带CPU上下文

我们可以把一个协程 切换到另一个协程。 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的


协程和线程的差异

线程切换从系统层面远不止保存和恢复 CPU上下文这么简单

操作系统为了程序运行的高效性每个线程都有自己缓存Cache等等数据,操作系统还会帮你做这些数据的恢复操作。 所以线程的切换非常耗性能。但是协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住


协程带来的问题

目前的协程框架一般都是设计成 1:N 模式。所谓 1:N 就是一个线程作为一个容器里面放置多个协程。 那么谁来适时的切换这些协程?答案是有协程自己主动让出CPU,也就是每个协程池里面有一个调度器, 这个调度器是被动调度的。意思就是他不会主动调度。而且当一个协程发现自己执行不下去了(比如异步等待网络的数据回来,但是当前还没有数据到), 这个时候就可以由这个协程通知调度器,这个时候执行到调度器的代码,调度器根据事先设计好的调度算法找到当前最需要CPU的协程。 切换这个协程的CPU上下文把CPU的运行权交个这个协程,直到这个协程出现执行不下去需要等等的情况,或者它调用主动让出CPU的API之类,触发下一次调度。


调度器<----协程,调度器---->协程


协程的好处

在高IO密集型的程序下很好。但是高CPU密集型的程序下没啥好处


greenlet版本实现协程案例,看起来好容易


gevent实现协程案例


import threading

import asyncio


@asyncio.coroutine

def hello():

    print('Hello world! (%s)' % threading.currentThread())

    yield from asyncio.sleep(1)

    print('Hello again! (%s)' % threading.currentThread())


loop = asyncio.get_event_loop()

tasks = [hello(), hello()]

#loop.run_until_complete(asyncio.wait(tasks))

for i in tasks:

    loop.run_until_complete(i)

loop.close()


从注释这个,可以看出协程的作用了

asyncio.wait,通过它可以获取一个协同程序的列表,同时返回一个将它们全包括在内的单独的协同程序


当两个hello方法,放入一个wait中,会同时执行,意味着没有阻塞的部分,会同时执行,然后必须等到阻塞完成后,同时返回,并继续循环。


import asyncio


@asyncio.coroutine

def wget(host):

    print('wget %s...' % host)

    connect = asyncio.open_connection(host, 80)

    reader, writer = yield from connect

    header = 'GET / HTTP/1.0\r\nHost: %s\r\n\r\n' % host

    writer.write(header.encode('utf-8'))

    yield from writer.drain()

    #不甚了解asyncio模块的writer函数, 但是从代码来看, 它是直接写出到TCP连接的, 也就是http的sever端

    while True:

        line = yield from reader.readline()

        yield from asyncio.sleep(1)

        if line == b'\r\n':

        #readline函数如果返回了\r\n就说明这一行是空行;

            break

        print('%s header > %s' % (host, line.decode('utf-8').rstrip()))

    # Ignore the body, close the socket

    writer.close()


loop = asyncio.get_event_loop()

tasks = [wget(host) for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']]

loop.run_until_complete(asyncio.wait(tasks))

loop.close()


await是异步等待, 既然你已经知道了控制权会被交出去, 那么就说明他自己是不可能自己恢复的, 必须等待外部程序(python解释器)利用send重新启动切换时的执行现场.



总结

协程用自己的话,来说,就是并行执行多个任务,自己定义切换任务的顺序,对于io等待类应用有用。

反正碰到yield from 理解为阻塞就行了。



本文转自 liqius 51CTO博客,原文链接:http://blog.51cto.com/szgb17/1941003,如需转载请自行联系原作者
相关文章
|
1月前
|
并行计算 调度 开发者
深入浅出Python协程:提升你的异步编程效率
在当今快速发展的软件开发领域,异步编程已成为提高程序性能和用户体验的关键技术。Python,作为一门广泛使用的高级编程语言,其协程(Coroutine)功能为开发者提供了强大的异步编程工具。本文将从协程的基本概念入手,通过实例深入浅出地讲解如何在Python中有效利用协程来提升异步编程的效率和可读性。我们将探讨协程的工作原理、与传统多线程/多进程相比的优势,以及如何在实际项目中应用协程来解决复杂的并发问题。通过本文的学习,读者将能够掌握Python协程的核心知识,为构建高效、可维护的异步应用奠定坚实基础。
|
6天前
|
调度 Python
Python多线程、多进程与协程面试题解析
【4月更文挑战第14天】Python并发编程涉及多线程、多进程和协程。面试中,对这些概念的理解和应用是评估候选人的重要标准。本文介绍了它们的基础知识、常见问题和应对策略。多线程在同一进程中并发执行,多进程通过进程间通信实现并发,协程则使用`asyncio`进行轻量级线程控制。面试常遇到的问题包括并发并行混淆、GIL影响多线程性能、进程间通信不当和协程异步IO理解不清。要掌握并发模型,需明确其适用场景,理解GIL、进程间通信和协程调度机制。
25 0
|
28天前
|
API 数据处理 调度
Python中的异步编程与协程应用
传统的Python编程在处理IO密集型任务时常常面临效率低下的问题,而异步编程和协程技术的引入为解决这一问题提供了有效的途径。本文将介绍Python中异步编程的基本概念,深入探讨asyncio库的使用以及协程在实际项目中的应用,旨在帮助开发者更好地理解和运用异步编程技术。
|
1月前
|
调度 Python
python协程—asyncio模块
python协程—asyncio模块
24 0
|
1月前
|
API 开发者 Python
深入浅出Python协程:提升并发编程效率
在当今高速发展的互联网时代,高并发成为了软件开发中的一个重要需求。本文将引领读者深入理解Python中的协程(Coroutine)概念,探讨其在并发编程中的应用及优势。我们将从协程的基础概念出发,通过实例讲解如何使用asyncio库来编写高效的异步代码。文章旨在帮助读者掌握协程的工作原理和使用方法,从而在实际开发中能够更好地利用Python进行高效的并发编程。
|
1月前
|
数据采集 调度 开发者
深入浅出Python协程:提升并发编程效率
本文旨在为读者揭开Python协程的神秘面纱,通过深入浅出的方式阐述其工作原理及应用场景。不同于传统的技术文章摘要,我们将以一种独特的视角,将协程比作一场精心编排的交响乐,其中每一个乐章都是一个独立的任务,共同演绎出并发编程的华丽篇章。文章将从协程的基本概念切入,通过对比线程和进程,逐步深入到事件循环、异步IO等核心机制,最后通过案例分析,让读者能够掌握使用Python协程处理高并发任务的技巧,从而提升编程效率。
|
1月前
|
程序员 开发者 Python
深入浅出Python协程:提升代码效率的秘诀
【2月更文挑战第12天】 在当今追求高效编程的时代,Python协程成为了开发者提升代码执行效率的重要工具。本文将以通俗易懂的方式,深入探讨Python协程的原理、使用方法及其在实际开发中的应用场景。通过对比传统同步编程和异步编程的差异,我们将揭示协程如何在不牺牲代码可读性的前提下,显著提高程序的运行效率。文章旨在为Python开发者提供一份全面、实用的协程学习指南,帮助他们在实际项目中更好地利用这一强大的特性。
22 2
|
2月前
|
调度 Python
什么是Python中的协程(Coroutine)?如何使用`async`和`await`进行协程编程?
什么是Python中的协程(Coroutine)?如何使用`async`和`await`进行协程编程?
27 0
|
2月前
|
程序员 Python
Python并发编程之协程与多线程对比分析
本文通过对Python中协程和多线程的特点、优缺点以及适用场景进行深入比较分析,帮助读者更好地理解并发编程中不同技术方案的选择与应用。
|
2月前
|
Java 调度 Python
python协程
我们知道线程的提出是为了能够在多核cpu的情况下,达到并行的目的。而且线程的执行完全是操作系统控制的。而协程(Coroutine)是线程下的,控制权在于用户,本质是为了能让多组过程能不独自占用完所有资源,在一个线程内交叉执行,达到高并发的目的。【2月更文挑战第4天】
37 1