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


相关文章
|
21天前
|
调度 Python
python知识点100篇系列(20)-python协程与异步编程asyncio
【10月更文挑战第8天】协程(Coroutine)是一种用户态内的上下文切换技术,通过单线程实现代码块间的切换执行。Python中实现协程的方法包括yield、asyncio模块及async/await关键字。其中,async/await结合asyncio模块可更便捷地编写和管理协程,支持异步IO操作,提高程序并发性能。协程函数、协程对象、Task对象等是其核心概念。
|
11天前
|
NoSQL 关系型数据库 MySQL
python协程+异步总结!
本文介绍了Python中的协程、asyncio模块以及异步编程的相关知识。首先解释了协程的概念和实现方法,包括greenlet、yield关键字、asyncio装饰器和async/await关键字。接着详细讲解了协程的意义和应用场景,如提高IO密集型任务的性能。文章还介绍了事件循环、Task对象、Future对象等核心概念,并提供了多个实战案例,包括异步Redis、MySQL操作、FastAPI框架和异步爬虫。最后提到了uvloop作为asyncio的高性能替代方案。通过这些内容,读者可以全面了解和掌握Python中的异步编程技术。
31 0
|
11天前
|
数据采集 缓存 程序员
python协程使用教程
1. **协程**:介绍了协程的概念、与子程序的区别、优缺点,以及如何在 Python 中使用协程。 2. **同步与异步**:解释了同步与异步的概念,通过示例代码展示了同步和异步处理的区别和应用场景。 3. **asyncio 模块**:详细介绍了 asyncio 模块的概述、基本使用、多任务处理、Task 概念及用法、协程嵌套与返回值等。 4. **aiohttp 与 aiofiles**:讲解了 aiohttp 模块的安装与使用,包括客户端和服务器端的简单实例、URL 参数传递、响应内容读取、自定义请求等。同时介绍了 aiofiles 模块的安装与使用,包括文件读写和异步迭代
14 0
|
1月前
|
数据处理 Python
深入探索:Python中的并发编程新纪元——协程与异步函数解析
深入探索:Python中的并发编程新纪元——协程与异步函数解析
26 3
|
2月前
|
Python
Python中的异步编程与协程实践
【9月更文挑战第28天】本文旨在通过一个简单易懂的示例,介绍如何在Python中利用asyncio库实现异步编程和协程。我们将通过代码示例来展示如何编写高效的并发程序,并解释背后的原理。
|
2月前
|
数据库 开发者 Python
实战指南:用Python协程与异步函数优化高性能Web应用
在快速发展的Web开发领域,高性能与高效响应是衡量应用质量的重要标准。随着Python在Web开发中的广泛应用,如何利用Python的协程(Coroutine)与异步函数(Async Functions)特性来优化Web应用的性能,成为了许多开发者关注的焦点。本文将从实战角度出发,通过具体案例展示如何运用这些技术来提升Web应用的响应速度和吞吐量。
28 1
|
2月前
|
调度 Python
揭秘Python并发编程核心:深入理解协程与异步函数的工作原理
在Python异步编程领域,协程与异步函数成为处理并发任务的关键工具。协程(微线程)比操作系统线程更轻量级,通过`async def`定义并在遇到`await`表达式时暂停执行。异步函数利用`await`实现任务间的切换。事件循环作为异步编程的核心,负责调度任务;`asyncio`库提供了事件循环的管理。Future对象则优雅地处理异步结果。掌握这些概念,可使代码更高效、简洁且易于维护。
24 1
|
2月前
|
调度 开发者 Python
探索Python中的异步编程:理解asyncio和协程
【9月更文挑战第22天】在现代软件工程中,异步编程是提升应用性能的关键技术之一。本文将深入探讨Python语言中的异步编程模型,特别是asyncio库的使用和协程的概念。我们将了解如何通过事件循环和任务来处理并发操作,以及如何用协程来编写非阻塞的代码。文章不仅会介绍理论知识,还会通过实际的代码示例展示如何在Python中实现高效的异步操作。
|
1月前
|
数据采集 调度 Python
Python编程异步爬虫——协程的基本原理(一)
Python编程异步爬虫——协程的基本原理(一)
|
1月前
|
数据采集 Python
Python编程异步爬虫——协程的基本原理(二)
Python编程异步爬虫——协程的基本原理(二)
下一篇
无影云桌面