当前位置: 刻度器 >> 刻度器优势 >> Python38异步并发编程虫虫搜奇
有效的提高程序执行效率的两种方法是异步和并发,Golang,node.js之所以可以有很高执行效率主要是他们的协程和异步并发机制。实际上异步和并发是每一种现代语言都在追求的特性,当然Python也不例外,今天我们就讲讲Python3中的异步并发编程。
概述
Python标准库提供了许多模块来处理异步并发和多进程任务,包括:
本文中,我们主要以于asyncio和concurrent.futures为主讲讲Python中异步和并发机制及实例。当然你也可能正在使用_thread和threading,但是无疑最应用用multiprocessing和concurrent.futures。
基本理论
异步编程
编写并发代码(使用_thread或threading模块)的是为了解决大家对CPU调用和中断的问题(因为CPU中一次只能运行一个线程),这涉及了CPU上下文切换的成本,虽然速度很快,但是也需要消耗资源。而且还要处理条件竞争,死锁/实时和资源不足(某些线程被过度使用,而其他线程未被充分利用)等等的问题。而这些正是异步任务可以避免的。
asyncio
asyncio是一个标准库,用于使用asyn/cawait语法编写并发代码。asyncio模块分别提供了高级和低级API。库和框架开发人员将使用低级API,同时鼓励使用不同于更传统threading或multiprocess异步代码执行方法。它利用事件循环的来处理异步任务的调度,而不是传统的线程或子进程。
需要提及的是asyncio是为了解决I/O性能,而不是CPU绑定操作。因此,asyncio不是所有类型的异步执行的替代品。
asyncio基于合作多任务的概念设计的,因此可以完全控制CPU上下文切换发生的时间(即上下文切换发生在应用程序级别,而不是硬件级别)。
使用asyncio,Python调度器负责管理,因此应用程序可能随时进行上下文切换)。
所以使用asyncio时,还需要使用某种形式的锁定机制来防止多个线程访问/更改共享内存(否则可能会破坏程序的线程安全)。
concurrent.futures
concurrent.futures模块是为异步执行可调用项提供高级接口,为thread和multiprocessing模块提供了高级抽象,这就是为什么本文没有详细讨论这些模块的原因。事实上,_thread模块是一个非常低级别的API,_threading模块本身是建立在它之上的。
前面我们已经提到,异步可以帮助我们避免使用线程,那么,如果它只是线程(和多处理)上的抽象,那么为什么要使用concurrent.futures呢?嗯,因为并非所有库/模块/API都支持异步模型。
例如,如果使用boto3和AWSS3并与之交互,就会发现这些是同步操作。可以在多线程代码中包装这些调用,但最好使用concurrent.futures,因为这样不仅受益于传统线程,而且受益于异步友好特性。该模块还设计为和异步事件循环互操作,从而更轻松地在异步驱动应用程序中处理线程/子进程池。
此外,当需要线程池或子进程池时,还需要利用concurrent.futures,同时可以使用干净而现代的PythonAPI。
绿色线程
实现异步编程的方法有很多种。有事件循环方法(异步实现),这种回调风格是JavaScript等单线程语言一直采用的方法。传统上还有一个称为绿色线程的概念。
从本质上讲,绿色线程的外观和感觉与普通线程完全一样,只不过线程是由应用程序代码而不是硬件安排的。因此,可以有效地处理(与事件循环一样)的确定性上下文切换问题。但是处理共享内存同样存在问题。
因此,让我们现在快速看看什么是事件循环,因为它是使异步工作的基础,为什么我们可以避免回调地狱和与绿色线程固有的问题...
事件循环
所有异步应用程序的核心元素是事件循环。事件循环是计划并运行异步任务的内容,它还包括处理网络IO操作和子进程运行。
异步事件循环非常有效,是因为它由Python内部在生成器实现的。生成器使函数能够部分执行,然后在特定点停止,维护一堆对象和异常,然后再恢复。
可等待性
异步背后的驱动力是计划异步任务的能力。Python中有几个不同类型的对象有助于支持此功能,它们通常通过Awaitables(可等待)进行分组。
如果某物可以在表达式中使用,它是可以等待的。await有三种主要的等待类型:
协程、任务和Future。
注意:Future是一种低级类型,因此,如果不是库/框架开发人员,则无需过多考虑它。
协程
协程属于可等待对象,因此可以在其他协程中被等待。协程中两个重要的概念:协程函数,定义为asyncdef的函数。
协程对象:通过调用协程函数所返回的对象。
asyncio基于生成器的协程函数修饰函数定义的函数将被async/await语法取代,但将继续支持,直到Python3.10
任务
任务用于同时安排协同程序。所有异步应用程序通常(至少)具有单个主入口点任务,该任务将安排在事件循环上立即运行。这是使用asyncio.run函数完成的。
协同例程函数预计将传递给asyncio.run,而内部异步将使用帮助器函数coroutines.iscoroutine检查该函数。如果不是协同程序,则引发错误,否则协同例程将传递给loop.run_until_
转载请注明:http://www.aideyishus.com/lkgx/3859.html