欢迎来到皮皮网网首页

【数字溯源码】【sqlserver源码解析】【试玩aqq源码】python future 源码

来源:源码 中文 时间:2024-11-24 17:51:32

1.Python:并发编程之Future
2.在Python中使用Asyncio系统(3-4)​Task 和 Future
3.python2.7.12中如何引用模块做整数相除
4.从c++20协程的源码使用彻底搞懂协程的本质

python future 源码

Python:并发编程之Future

       学习并发编程时,首先得区分并发与并行。并发(concurrency)对应的源码是 Python 中的多线程或协程,意味着在同一时刻只能运行一个线程或协程,源码通过不断地切换实现并发处理,源码适用于 I/O 频繁的源码操作。并行(parallelism)则对应多进程,源码数字溯源码在多个 CPU 上同时运行,源码适用于 CPU 密集型的源码操作。

       线程在 Python 中由操作系统底层提供,源码它能跟踪每个线程的源码信息,并在适当的源码时候自动进行线程切换,无需我们手动调度。源码然而,源码这也容易引发 race condition。源码sqlserver源码解析引入线程概念的源码原因在于,单线程程序往往效率低下,多线程版本则能显著提升速度。

       对比单线程与多线程,单线程程序按照顺序执行,每一步都需要等待 I/O 操作完成,因此整体速度较慢。而多线程版本通过创建线程池,利用 ThreadPoolExecutor 类,设置最大线程数,如 max_workers 参数,可实现并行处理,显著提高下载速度。试玩aqq源码

       在多线程代码中,map 方法被用于并发调用函数,类似普通的内置 map 函数,但效率更高。requests.get 函数线程安全,因此在多线程环境下,它不会引发 race condition。然而,线程切换由操作系统负责,可能会导致结果乱序。

       Future 是并发编程的关键概念,是 concurrent.futures 模块和 asyncio 模块的重要组成部分。Future 类代表一个尚未完成或已完成的自阅源码延迟计算任务,类似于 JavaScript 中的 Promise 对象。通常情况下,不应直接创建 Future 实例,而是通过并发框架(如 concurrent.futures 和 asyncio)来生成实例,因为 Future 表示即将发生的事情,其执行时间已经排定。

       生成 Future 实例的方法是通过 Executor 子类为需要排定的某件事安排执行。了解 Executor.submit 方法用于接收一个可调用对象,并为其安排执行,返回一个 Future 实例。Executor.map 方法则用于并行处理一系列任务,返回一个迭代器,迭代器的野心玩家源码 __next__ 方法会调用各个 Future 实例的结果。

       Future 实例具有状态,可以是 running、pending 或 finished。Future.done() 方法用于立即返回布尔值,表示 Future 是否已完成。Future.add_done_callback 方法允许在 Future 运行结束后调用一个可调用对象。Future.result 方法用于获取 Future 的结果,如果在执行结束时调用,则返回可调用对象的结果或异常。如果 Future 还未完成,且 timeout 参数被指定,调用 Future.result() 方法会阻塞调用方所在的线程,直到有结果返回,或抛出 TimeoutError 异常。

       concurrent.futures.as_completed 是一个迭代器,接收 Future 列表,返回在 Future 运行结束后产出的 Future。通过 Executor.submit 创建 Future,使用 as_completed 进行管理,可实现更精细的并发控制。

在Python中使用Asyncio系统(3-4)​Task 和 Future

        Task 和 Future

        前面我们讨论了协程,以及如何在循环中运行它们才有用。现在我想简单谈谈Task和Future api。你将使用最多的是Task,因为你的大部分工作将涉及使用create_task()函数运行协程,就像在第页的“快速开始”中设置的那样。Future类实际上是Task的超类,它提供了与循环交互操作的所有功能。

        可以这样简单地理解:Future表示某个活动的未来完成状态,并由循环管理。Task是完全相同的,但是具体的“activity”是一个协程——可能是你用async def函数加上create_task()创建的协程。

        Future类表示与循环交互的某个东西的状态。这个描述太模糊了,不太有用,所以你可以将Future实例视为一个切换器,一个完成状态的切换器。当创建Future实例时,切换设置为“尚未完成”状态,但稍后它将是“完成”状态。事实上,Future实例有一个名为done()的方法,它允许你检查状态,如示例 3-所示。

        示例 3-. 用done()方法检查完成状态

        Future实例还可以执行以下操作:

        • 设置一个result值(用.set_result(value)设置值并且使用 .result()获取值)

        • 使用.cancel()方法取消 (并且会用使用.cancelled()检查是否取消)

        • 增加一个Future完成时回调的函数

        即使Task更常见,也不可能完全避免使用Future:例如,在执行器上运行函数将返回Future实例,而不是Task。让我们快速看一下 示例 3- ,了解一下直接使用Future实例是什么感觉。

        示例 3-. 与Future实例的交互

        (L3)创建一个简单的 main函数。我们运行这个函数,等上一会儿然后在Future f上设置一个结果。

        (L5)设置一个结果。

        (L8)手动创建一个Future实例。注意,这个实例(默认情况下)绑定到我们的循环,但它没有也不会被附加到任何协程(这就是Tasks的作用)。

        (L9)在做任何事情之前,确认future还没有完成。

        (L)安排main()协程,传递future。请记住,main()协程所做的所有工作就是sleep,然后切换Future实例。(注意main()协程还不会开始运行:协程只在事件循环运行时才开始运行。)

        (L)在这里我们在Future实例上而不是Task实例上使用run_until_complete()。这和你以前见过的不一样。现在循环正在运行,main()协程将开始执行.

        (L)最终,当future的结果被设置时,它就完成了。完成后,可以访问结果。

        当然,你不太可能以这里所示的方式直接使用Future;代码示例仅用于教育目的。你与asynccio的大部分联系都是通过Task实例进行的。

        你可能想知道如果在Task实例上调用set_result()会发生什么。在Python 3.8之前可以这样做,但现在不允许这么做了。任务实例是协程对象的包装器,它们的结果值只能在内部设置为底层协程函数的结果,如 示例 3-所示那样。

        示例 3-. 在task上调用set_result

        (L)唯一的区别是我们创建的是Task实例而不是Future实例。当然,Task API要求我们提供一个协程;这里我们使用sleep()只是因为简单方便。

        (L7)正在传入一个Task实例。它满足函数的类型签名(因为Task是Future的子类),但从Python 3.8开始,我们不再允许在Task上调用set_result():尝试这样做将引发RuntimeError。这个想法是,一个Task代表一个正在运行的协程,所以结果应该总是来自于task自身。

        (L, L)但是,我们仍然可以cancel()一个任务,它将在底层协程中引发CancelledError。

        Create_task? Ensure_Future? 下定决心吧!

        在第页的“快速入门”中,我说过运行协程的方法是使用asyncio.create_task()。在引入该函数之前,有必要获取一个循环实例并使用loop.create_task()完成相同的任务。事实上,这也可以通过一个不同的模块级函数来实现:asyncio.ensure_future()。一些开发人员推荐create_task(),而其他人推荐ensure_future()。

        在我为这本书做研究的过程中,我确信API方法asyncio.ensure_future()是引起对asyncio库广泛误解的罪魁祸首。API的大部分内容都非常清晰,但在学习过程中还存在一些严重的障碍,这就是其中之一。当你遇到ensure_future()时,你的大脑会非常努力地将其集成到关于asyncio应该如何使用的心理模型中——但很可能会失败!

        在Python 3.6 asyncio 文档中,这个现在已经臭名昭著的解释突出了 ensure_future() 的问题:

        asyncio.ensure_future(coro_or_future, *, _loop =None)

        安排执行一个协程对象:把它包装在future中。返回一个Task对象。如果参数是Future,则直接返回。

        什么!? 当我第一次读到这篇文章时,我很困惑。下面希望是对ensure_future()的更清楚的描述:

        这个函数很好地说明了针对终端用户开发人员的asyncio API(高级API)和针对框架设计人员的asyncio API(低级API)之间的区别。让我们在示例 3-中自习看看它是如何工作的。

        示例 3-. 仔细看看ensure_future()在做什么

        (L3)一个简单的什么都不做的协程函数。我们只需要一些能组成协程的东西。

        (L6)我们通过直接调用该函数来创建协程对象。你的代码很少会这样做,但我想在这里明确地表示,我们正在向每个create_task()和ensure_future()传递一个协程对象。

        (L7)获取一个循环。

        (L9)首先,我们使用loop.create_task()在循环中调度协程,并返回一个新的Task实例。

        (L)验证类型。到目前为止,没有什么有趣的。

        (L)我们展示了asyncio.ensure_future()可以被用来执行与create_task()相同的动作:我们传入了一个协程,并返回了一个Task实例(并且协程已经被安排在循环中运行)!如果传入的是协程,那么loop.create_task()和asyncio.ensure_future()之间没有区别。

        (L)如果我们给ensure_future()传递一个Task实例会发生什么呢?注意我们要传递的Task实例是已经在第4步通过loop.create_task()创建好的。

        (L)返回的Task实例与传入的Task实例完全相同:它在被传递时没有被改变。

        直接传递Future实例的意义何在?为什么用同一个函数做两件不同的事情?答案是,ensure_future()的目的是让框架作者向最终用户开发者提供可以处理两种参数的API。不相信我?这是ex-BDFL自己说的:

        ensure_future()的要点是,如果你有一个可能是协程或Future(后者包括一个Task,因为它是Future的子类)的东西,并且你想能够调用一个只在Future上定义的方法(可能唯一有用的例子是cancel())。当它已经是Future(或Task)时,它什么也不做;当它是协程时,它将它包装在Task中。

        如果您知道您有一个协程,并且希望它被调度,那么正确的API是create_task()。唯一应该调用ensure_future()的时候是当你提供一个API(像大多数asyncio自己的API),它接受协程或Future,你需要对它做一些事情,需要你有一个Future。

        —Guido van Rossum

        总而言之,asyncio.sure_future()是一个为框架设计者准备的辅助函数。这一点最容易通过与一种更常见的函数进行类比来解释,所以我们来做这个解释。如果你有几年的编程经验,你可能已经见过类似于例3-中的istify()函数的函数。示例 3-中listify()的函数。

        示例 3-. 一个强制输入列表的工具函数

        这个函数试图将参数转换为一个列表,不管输入的是什么。api和框架中经常使用这类函数将输入强制转换为已知类型,这将简化后续代码——在本例中,您知道参数(来自listify()的输出)将始终是一个列表。

        如果我将listify()函数重命名为ensure_list(),那么您应该开始看到与asyncio.ensure_future()的类似之处:它总是试图将参数强制转换为Future(或子类)类型。这是一个实用函数,它使框架开发人员(而不是像你我这样的终端用户开发人员)的工作变得更容易。

        实际上,asyncio标准库模块本身使用ensure_future()正是出于这个原因。当你下次查看API时,你会发现函数参数被描述为“可等待对象”,很可能内部使用ensure_future()强制转换参数。例如,asyncio.gather()函数就像下面的代码一样:

        aws参数表示“可等待对象”,包括协程、task和future。在内部,gather()使用ensure_future()进行类型强制转换:task和future保持不变,而把协程强制转为task。

        这里的关键是,作为终端用户应用程序开发人员,应该永远不需要使用asyncio.ensure_future()。它更像是框架设计师的工具。如果你需要在事件循环上调度协程,只需直接使用asyncio.create_task()来完成。

        在接下来的几节中,我们将回到语言级别的特性,从异步上下文管理器开始。

python2.7.中如何引用模块做整数相除

       set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等,也就无法保证set内部“不会有重复元素”。试试把list放入set,看看是否会报错

从c++协程的使用彻底搞懂协程的本质

       什么是协程

       协程是可中断的函数,它能够暂停执行并保存当前状态,在后续时刻恢复执行。简单来说,协程就是可以暂停和恢复的函数。

       如何实现协程

       例如在Python中,我们可以定义一个协程函数,并通过调用`next`函数来启动它。在执行过程中,协程可以中断,并在稍后通过再次调用`next`来恢复执行。例如:

       python

       def test():

        print('begin')

        yield

        print('end')

        yield

       test_gen = test()

       print(next(test_gen))

       print(next(test_gen))

       调度器

       调度器是管理协程执行的关键组件。它按顺序执行协程,可以用来实现定时协程、IO协程等功能。以Python协程为例,调度器通过循环取出协程,将协程“复苏”以继续执行。

       python

       import asyncio

       async def test():

        print('begin')

        await asyncio.sleep(1)

        print('end')

       async def main():

        asyncio.ensure_future(test())

        asyncio.get_event_loop().run_forever()

       asyncio.run(main())

       C++协程

       C++标准引入了对协程的支持,允许在C++中定义协程。实现协程的关键是定义符合特定接口的函数。例如:

       cpp

       #include

       #include

       class Scheduler {

       public:

        void ensure_future(std::future future) {

        // 将协程放入调度器的队列

        }

        void run_until_no_task() {

        // 启动调度器执行协程

        }

       };

       void task1() {

        // 协程的实现

       }

       int main() {

        Scheduler sche;

        sche.ensure_future(std::async(std::launch::async, task1));

        sche.run_until_no_task();

        return 0;

       }

       为了使用C++协程,需要下载并编译libfuture库,该库包含了一个调度器实现。使用libfuture库,我们可以轻松创建和执行协程,如下所示:

       cpp

       #include

       void task1() {

        // 协程实现

       }

       int main() {

        libfuture::current_scheduler().ensure_future(libfuture::async(task1));

        libfuture::current_scheduler().run_until_no_task();

        return 0;

       }

       libfuture库还提供了内置的协程,如`open_accept`、`open_connection`、`buffer_read`和`buffer_write`,用于I/O操作。通过这些协程,可以实现异步I/O,提高程序的性能。

       总结

       通过定义协程函数并使用调度器管理执行顺序,我们可以实现灵活的并发执行和异步操作。C++协程的引入使C++程序员能够编写更高效、更易于维护的并发程序。通过使用第三方库如libfuture,我们可以轻松实现协程功能,并利用其提供的内置协程实现复杂操作,如网络通信和文件读写等。