asyncio和trio之间的核心区别是什么?

Sra*_*raw 44 python asynchronous python-asyncio curio python-trio

今天,我找到了一个名为trio的库,它表示自己是一个针对人类的异步API.这些词与requests' 有点类似.由于这requests是一个很好的图书馆,我想知道它的优点是什么trio.

关于它的文章不多,我只是找到一篇文章讨论curioasyncio.令我惊讶的是,trio它本身甚至比curio(下一代古玩)更好.

阅读完一半文章后,我找不到这两个异步框架之间的核心区别.它只是给出了一些实例curio比实现更方便的例子asyncio.但底层结构几乎相同(基于回调,我认为所有异步IO框架都基于回调而没有任何异常.)

那么有人能给我一个理由我必须接受trio或者curio更好asyncio吗?或者解释一下为什么我应该选择trio而不是内置asyncio

Nat*_*ith 91

我来自哪里:我是三人组的主要作者.我也是古玩的主要贡献者之一(并撰写了关于它的链接的文章),以及一个积极参与有关如何改进asyncio的讨论的Python核心开发者.

我不确定你对回调的意思.在trio(和curio)中,核心设计原则之一就是你从不用回调编程; 感觉更像基于线程的编程而不是基于回调的编程.我想如果你打开引擎盖并看看它们是如何在内部实现的,那么有些地方它们会使用回调,或者如果你眯着眼睛那么等同于回调的东西.但这就像说Python和C是等价的,因为Python解释器是用C实现的.永远不会使用回调.

无论如何:

Trio vs asyncio

Asyncio更成熟

第一个巨大的差异是生态系统的成熟度.在我写这篇的时候2018三月,有很多更多的图书馆与ASYNCIO支持超过三人的支持.例如,现在没有任何真正的HTTP服务器支持三人组.PyPI上Framework :: AsyncIO分类器目前有122个库,而Framework :: Trio分类器只有8个.我希望答案的这一部分很快就会过时 - 例如,这里的Kenneth Reitz试验在下一个版本的请求中添加三重奏支持 - 但是现在,你应该期望如果你有任何复杂的三重奏,那么你将遇到需要自己填写的缺失部分,而不是从pypi抓取一个库或者您需要使用trio-asyncio包,它允许您在三重奏程序中使用asyncio库.(三重聊天频道对于了解可用内容以及其他人正在进行的工作非常有用.)

Trio使您的代码更简单

就实际的图书馆而言,它们也非常不同.三重奏的主要论点是它使编写并发代码比使用asyncio简单得多.当然,当你最后一次听到有人说他们的图书馆让事情变得更难使用时......让我举一个具体的例子.在本演讲(幻灯片)中,我使用了实现RFC 8305"Happy eyeballs"的示例,这是一种用于有效建立网络连接的简单并发算法.这是Glyph多年来一直在思考的问题,他最新版本的Twisted长约600行.(Asyncio大致相同; Twisted和asyncio在架构上非常相似.)在演讲中,我教你使用trio在<40行中实现它所需要知道的一切(我们修复了他的版本中的错误)在它).所以在这个例子中,使用trio字面意思使我们的代码更简单一个数量级.

你也可以找到用户感兴趣的这些评论:1,2,3

细节上有很多不同之处

为什么会这样?这是一个更长的答案:-).我正在逐步编写博客文章和会谈中的不同部分,我将尽力记住在链接可用时更新此答案.基本上,它归结为Trio有一小部分精心设计的原语,与我所知道的任何其他库有一些根本区别(虽然当然建立在很多地方的想法上).这里有一些随机笔记给你一些想法:

asyncio和相关库中一个非常常见的问题是你调用some_function()它返回,所以你认为它已经完成了 - 但实际上它仍然在后台运行.这会导致各种棘手的错误,因为它很难控制事情发生的顺序,或者知道什么时候实际完成,并且它可以直接隐藏问题,因为如果后台任务因未处理的异常崩溃,asyncio将通常只是打印一些东西到控制台,然后继续前进.在三重奏中,我们通过"托儿所"处理任务产生的方式意味着这些事情都不会发生:当一个函数返回时你知道它已经完成,而Trio目前是Python的唯一并发库,异常总是传播直到你抓住它们.

Trio管理超时和取消的方式是新颖的,我认为比以前最先进的系统如C#和Golang更好.我确实写过一篇关于此的文章,所以我不会在这里详述所有细节.但是asyncio的取消系统 - 或者说真的是系统,它有两个语义略有不同 - 基于比C#和Golang更古老的想法,并且很难正确使用.(例如,代码很容易通过生成后台任务来"逃避"取消;请参阅上一段.)

在asyncio中有大量冗余的东西,这使得很难分辨出什么时候使用它.你有期货,任务和协同程序,这些都基本上用于相同的目的,但你需要知道它们之间的差异.如果你想实现一个网络协议,你必须选择是使用协议/传输层还是流层,它们都有棘手的陷阱(这就是你链接的文章的第一部分).

Trio目前是Python唯一的并发库,其中control-C的工作方式与您期望的一样(即,它会提升KeyboardInterrupt您的代码).这是一件小事,但它有很大的不同:-).出于各种原因,我不认为这在asyncio中是可以解决的.

加起来

如果您需要在下周将产品运送到生产中,那么您应该使用asyncio(或Twisted或Tornado或gevent,它们更加成熟).他们拥有庞大的生态系统,其他人在你之前就已经将它们用于生产,并且他们不会去任何地方.

如果试图使用这些框架让你感到沮丧和困惑,或者如果想尝试不同的做事方式,那么一定要检查三重奏 - 我们很友好:-).

如果你想在一年后把东西运到生产中......那么我不知道该告诉你什么.Python并发性正在变化.Trio在设计层面有很多优势,但足以克服asyncio的先声夺人?asyncio在标准库中是优势还是劣势?(注意这些日子每个人都使用requests,即使标准库有urllib.)trio中有多少新想法可以添加到asyncio中?没人知道.我希望今年PyCon会有很多有趣的讨论:-).

  • Trio的另一个优点是:当你需要将一个同步库转换为Trio时,通常只需要在需要异步上下文的部分就可以将async/await放到你需要的任何地方.如果事情更复杂,可以添加一个托儿所和几个任务.根据我的经验,Trio的概​​念很容易理解,调试Trio代码比围绕asyncio更容易. (7认同)
  • 现在还有“anyio”:“AnyIO 是一个异步网络和并发库,可在 asyncio 或 trio 之上工作。针对 AnyIO 的 API 编写的应用程序和库将无需修改即可在 asyncio 或 trio 上运行。” https://pypi.org/project/anyio/ (6认同)
  • "你有未来,任务和协同程序......"虽然我现在使用asyncio超过一年,但这个类似概念的动物园仍然让我感到厌烦. (4认同)
  • 非常感谢.很抱歉迟到的回复,因为我需要一些时间来阅读您的答案和参考.现在我觉得我更了解`trio`,它在设计原理方面确实有优势.在过去,我利用业余时间来理解`requests`的API设计原则,这对我设计与网络通信相关的API有很大帮助.虽然`trio`现在是新生的,但学习它可以改善我在async IO上的设计.再次感谢. (3认同)
  • @Ginko 不幸的是,这并不是真正的快乐眼球的实现。当一项任务成功完成时,您不会取消其他任务;您不处理被取消的父任务;如果上一个连接提前完成,您就不会加快下一个连接... asyncio 这里有一个令人高兴的眼球,您会发现它比这更复杂:https://github.com/twisteroidambassador/async_stagger 或者只是观看演讲,它会详细介绍:-) (3认同)
  • @ n1k31t4 Trio仍在继续成熟,但是截至2019年2月,我认为答案仍然基本准确– Trio具有许多理论优势,但仍处于“早期采用者”阶段。该[论坛上的最新帖子](https://trio.discourse.group/t/priorities-roadmap/34)可能使您对我们正在做的事情有所了解。对于将来寻求更新的用户,在论坛上或[chat](https://gitter.im/python-trio/general)询问是获得更新的快速方法。 (2认同)
  • *而 Framework :: Trio 分类器只有 8 个*。截至 2021 年 10 月,该数字同时增长至 **117**。就百分比而言,它从“asyncio”输出的 6.56% 增长到 11.91%(后者也没有跳过它,因为它从 122 增长到 982:))。另外“Twisted”结果是:323。 (2认同)
  • **S 级文章。** 我持怀疑态度,因为[`xkcd` 标准效果是真实的](https://xkcd.com/927)。在离开时,我几乎狂热地致力于在新项目中缓慢(但不可阻挡地)从“asyncio”转向 Trio。知识就是幸福。现在我有了。 (2认同)