协程间的Iterable流

sav.channels的Python项目详细描述


通道:协同程序之间的python迭代器流

这个包提供了一个简单易用的Channel类来发送和 在协同过程之间接收对象。

0.4版,版权所有)Sander Voerman,2019年。

安装

安装sav.channels 来自python包索引的包。见 installing packages 以便进一步指导。

概述

通道是两个协程之间的直接连接,通过它它们可以 发送和接收对象。

单纯形示例

每个通道都由客户端和服务器端组成。在对象的情况下 只向一个方向发送,client()方法返回接收 结束,可以使用async for进行迭代。server方法返回 一个上下文管理器,可以在 正在生成协同程序:

importasynciofromtypingimportAsyncIterator,AsyncGeneratorfromsav.channelsimportChannelfromfooimportFooasyncdefproduce(channel:Channel[Foo,None])->None:asyncwithchannel.server()asserver:awaitserver.asend(Foo("One"))awaitproduce_two(server)awaitserver.asend(Foo("Three"))asyncdefproduce_two(server:AsyncGenerator[None,Foo])->None:awaitserver.asend(Foo("Two"))asyncdefconsume(client:AsyncIterator[Foo])->None:asyncforfooinclient:print(foo)asyncdefmain()->None:channel=Channel()awaitasyncio.gather(consume(channel.client()),produce(channel))asyncio.run(main())

双工示例

channel.client()async with channel.server()返回的对象 都是asynchronous generators 支持双向交流。下面的例子 演示数据如何在两个方向上流过通道:

importasyncioimportitertoolsfromsav.channelsimportChannelasyncdefletters(channel:Channel[str,int])->None:asyncwithchannel.server()ass:# wait for the clientprint(awaits.asend("A"))# send and receiveprint(awaits.asend("B"))# send and receiveasyncdefnumbers(channel:Channel[str,int])->None:asend=channel.client().asendtry:print(awaitasend(None))# receive onlyforiinitertools.count():print(awaitasend(i))# send and receiveexceptStopAsyncIteration:passasyncdefmain()->None:channel=Channel()awaitasyncio.gather(letters(channel),numbers(channel))asyncio.run(main())

这将产生结果:

A
0
B
1

因此,通过通道发送的第一个项目是 服务器。async with块通过等待asend(None)来启动服务器, 在客户端启动并等待第一个项目 接收。当执行从async with块流出时,服务器是 通过等待aclose()关闭,这会导致等待的客户机引发 StopAsyncIteration

频道的目的

尽管向两个方向发送值的可能性在 在某些情况下,不是什么让频道有趣,也不是为什么我们需要 他们。渠道的目的在于它逆转 可以说,客户机和服务器生成器发送和 屈服值。

使用通道推入管道

如果一个值被发送到服务器生成器中,它将由 客户端生成器。这意味着您可以将客户端生成器传递给自己的 异步生成器函数,并使该函数从 通道,对其进行处理,并将结果传递给另一个生成器 你的处理管道。然而,每次管道请求 另一个来自频道的项目,正在等待 来自server.asend的结果恢复执行。这意味着从 对于生产者,管道看起来像一个reverse生成器。渠道给予 你不必写下逆向生成器管道的力量 反向发电机功能。

将生成器重构为生成器,反之亦然

通道的服务器上下文用于镜像 异步发电机功能:

asyncwithchan.server()ass:a=awaits.asend('One')b=awaits.asend('Two')c=awaits.asend('Three')asyncdefagen():a=yield'One'b=yield'Two'c=yield'Three'

通道和发生器功能之间的相似性使得 重构。例如,当只有一个协程发送值时 进入一个通道,除此之外它什么也不做(如 上面的例子),它应该 转换为异步生成器函数。另一方面, 异步生成器函数有某些限制 这会让他们变得笨拙。如果需要转动越来越多的功能 进入生成器函数,因为它们需要yield到其他生成器, 或者如果代码中充满了while True: f((yield))循环而不是 async for x: f(x)循环,将生成器函数重构为通道 可能是可取的。

从一个程序推入多个通道

通道允许更大的灵活性,因为您可以发送值 从单个函数或循环进入不同的通道,而 异步发电机功能与同步发电机功能相同 它只能屈服于同一生成器对象的生成器。

有效地委派给另一个生产商

异步生成器函数不支持yield from g顺序 委派给其他发电机。相反,你必须写 async for x in g: yield x(在单纯形情况下),这意味着事件 循环每次都必须跳进和跳出委托生成器 在它跳入生成生成器之前,因为 代码要求在每次迭代时更新x的值。 相反,使用async with时通道返回的对象可能 将产品委托给另一个协程,如 本文档顶部的第一个示例。

结合异步和同步迭代

StreamChannel类提供了额外的读写方法 允许发送多个项,甚至同步的非大小化迭代器, 通过通道,而不将控制权传递回 每一件物品。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java Midlet即使按下设备的“剪切”按钮也不能关闭   JavaSpring环境。getProperty未解析   用Hibernate在Java中实现序列   具有重复键和文件写入的java映射   java显示控制台输出到JavaFXML应用程序中的TextArea   java Cucumber在编译为时无法在类路径上找到功能文件。战争   java过滤器中的servlet问题   安卓中消息和字符串之间的java转换?   java Apache POI读取单元(下午12:35:00)时间值返回1899年12月31日   Java游戏中的碰撞检测?   JSF2.0中的JavajQuery   java在setValue之后使用不同的值   java如何修复可选文件的StackOverflow错误?   如何在不使用服务器设置的情况下使用java从Outlook mail下载附件?   YAxis上Java BoxLayout中单个字符的摆动对齐偏离中心