python 协程

简介: python 协程

python 协程

文章目录

1. 协程

协程 (coroutine),又称微线程,是一种用户级的轻量级线程。协程 拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他 地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此协程能保留上一 次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态。


在并发编程 中,协程与线程类似,每个协程表示一个执行单元,有自己的本地数据,与其他协 程共享全局数据和其他资源。协程需要用户自己来编写调度逻辑,对于CPU来说,协程其实是单线程,所以 CPU不用去考虑怎么调度、切换上下文,这就省去了CPU的切换开销,所以协程在一 定程度上又好于多线程。那么在Python中是如何实现协程的呢?


Python通过yield提供了对协程的基本支持,但是不完全,而使用第三方 gevent库是更好的选择,gevent提供了比较完善的协程支持。gevent是一个基于 协程的Python网络函数库,使用greenlet在libev事件循环顶部提供了一个有高级 别并发性的API。主要特性有以下几点:


·基于libev的快速事件循环,Linux上是epoll机制。

·基于greenlet的轻量级执行单元。

·API复用了Python标准库里的内容。

·支持SSL的协作式sockets。

·可通过线程池或c-ares实现DNS查询。

·通过monkey patching功能使得第三方模块变成协作式。

gevent对协程的支持,本质上是greenlet在实现切换工作。greenlet工作流 程如下:假如进行访问网络的IO操作时,出现阻塞,greenlet就显式切换到另一段 没有被阻塞的代码段执行,直到原先的阻塞状况消失以后,再自动切换回原来的代 码段继续处理。因此,greenlet是一种合理安排的串行方式。


由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换 协程,就保证总有greenlet在运行,而不是等待IO,这就是协程一般比多线程效率 高的原因。由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一 些标准库,将一些常见的阻塞,如socket、select等地方实现协程跳转,这一过程 在启动时通过monkey patch完成。下面通过一个的例子来演示gevent的使用流 程,代码如下:

from gevent import monkey; monkey.patch_all()
import gevent
import urllib.request
def run_task(url):
  print('Visit --> %s' % url)
  try:
      response = urllib.request.urlopen(url)
      data = response.read()
      print('%d bytes received from %s.' % (len(data), url))
  except Exception as e:
      print(e)
if __name__=='__main__':
  urls = ['https://github.com/','https://www.python.org/','http://www.cnblogs.com/']
  greenlets = [gevent.spawn(run_task, url) for url in urls ]
  gevent.joinall(greenlets)

输出:

$ python coroutine1.py 
Visit --> https://github.com/
Visit --> https://www.python.org/
Visit --> http://www.cnblogs.com/
50895 bytes received from https://www.python.org/.
75936 bytes received from http://www.cnblogs.com/.
307979 bytes received from https://github.com/.

以上程序主要用了gevent中的spawn方法和joinall方法。spawn方法可以看做

是用来形成协程,joinall方法就是添加这些协程任务,并且启动运行。从运行结

果来看,3个网络操作是并发执行的,而且结束顺序不同,但其实只有一个线程。


gevent中还提供了对池的支持。当拥有动态数量的greenlet需要进行并发管理

(限制并发数)时,就可以使用池,这在处理大量的网络和IO操作时是非常需要

的。接下来使用gevent中pool对象,对上面的例子进行改写,程序如下:

from gevent import monkey
monkey.patch_all()
import urllib.request
from gevent.pool import Pool
def run_task(url):
  print('Visit --> %s' % url)
  try:
    response = urllib.request.urlopen(url)
    data = response.read()
    print('%d bytes received from %s.' % (len(data), url))
  except Exception as e:
    print(e)
  return('url:%s --->finish'% url)
if __name__=='__main__':
  pool = Pool(2)
  urls = ['https://github.com/','https://www.python.org/','http://www.cnblogs.com/']
  results = pool.map(run_task,urls)
  print(results)

输出信息:

$ python coroutine2.py 
Visit --> https://github.com/
Visit --> https://www.python.org/
50895 bytes received from https://www.python.org/.
Visit --> http://www.cnblogs.com/
307979 bytes received from https://github.com/.
76015 bytes received from http://www.cnblogs.com/.
['url:https://github.com/ --->finish', 'url:https://www.python.org/ --->finish', 'url:http://www.cnblogs.com/ --->finish']

通过运行结果可以看出,Pool对象确实对协程的并发数量进行了管理,先访问

了前两个网址,当其中一个任务完成时,才会执行第三个。


参考:


Python爬虫开发与项目实战

gevent调度流程解析

Python process, thread and coroutine

Difference between Multi-Processing, Multi-threading and Coroutine

Choosing between Python threads vs coroutines vs processes

python process thread coroutine

Combining Coroutines with Threads and Processes


相关文章
|
1月前
|
并行计算 调度 开发者
深入浅出Python协程:提升你的异步编程效率
在当今快速发展的软件开发领域,异步编程已成为提高程序性能和用户体验的关键技术。Python,作为一门广泛使用的高级编程语言,其协程(Coroutine)功能为开发者提供了强大的异步编程工具。本文将从协程的基本概念入手,通过实例深入浅出地讲解如何在Python中有效利用协程来提升异步编程的效率和可读性。我们将探讨协程的工作原理、与传统多线程/多进程相比的优势,以及如何在实际项目中应用协程来解决复杂的并发问题。通过本文的学习,读者将能够掌握Python协程的核心知识,为构建高效、可维护的异步应用奠定坚实基础。
|
2天前
|
调度 Python
Python多线程、多进程与协程面试题解析
【4月更文挑战第14天】Python并发编程涉及多线程、多进程和协程。面试中,对这些概念的理解和应用是评估候选人的重要标准。本文介绍了它们的基础知识、常见问题和应对策略。多线程在同一进程中并发执行,多进程通过进程间通信实现并发,协程则使用`asyncio`进行轻量级线程控制。面试常遇到的问题包括并发并行混淆、GIL影响多线程性能、进程间通信不当和协程异步IO理解不清。要掌握并发模型,需明确其适用场景,理解GIL、进程间通信和协程调度机制。
17 0
|
23天前
|
API 数据处理 调度
Python中的异步编程与协程应用
传统的Python编程在处理IO密集型任务时常常面临效率低下的问题,而异步编程和协程技术的引入为解决这一问题提供了有效的途径。本文将介绍Python中异步编程的基本概念,深入探讨asyncio库的使用以及协程在实际项目中的应用,旨在帮助开发者更好地理解和运用异步编程技术。
|
1月前
|
调度 Python
python协程—asyncio模块
python协程—asyncio模块
20 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`进行协程编程?
26 0
|
2月前
|
程序员 Python
Python并发编程之协程与多线程对比分析
本文通过对Python中协程和多线程的特点、优缺点以及适用场景进行深入比较分析,帮助读者更好地理解并发编程中不同技术方案的选择与应用。
|
2月前
|
Java 调度 Python
python协程
我们知道线程的提出是为了能够在多核cpu的情况下,达到并行的目的。而且线程的执行完全是操作系统控制的。而协程(Coroutine)是线程下的,控制权在于用户,本质是为了能让多组过程能不独自占用完所有资源,在一个线程内交叉执行,达到高并发的目的。【2月更文挑战第4天】
37 1