我来自哪里:我是《三重奏》的主要作者。我也是 curio 的主要贡献者之一(并撰写了您链接到的有关它的文章),并且是一名 Python 核心开发人员,他积极参与有关如何改进 asyncio 的讨论。
在 trio(和 curio)中,核心设计原则之一是永远不要使用回调进行编程;感觉更像是基于线程的编程而不是基于回调的编程。我想,如果你打开引擎盖,看看它们的内部实现方式,就会发现它们在某些地方使用了回调,或者如果你眯着眼睛看的话,它们与回调相当。但这就像说 Python 和 C 是等效的,因为 Python 解释器是用 C 实现的。You永远不要使用回调。
Anyway:
Trio 与 asyncio
Asyncio 更加成熟
第一个大的区别是生态系统的成熟度。当时我正在写这个2018年3月, 有many支持 asyncio 的库多于支持 trio 的库。例如,现在还没有任何真正支持三重奏的 HTTP 服务器。这框架 :: PyPI 上的 AsyncIO 分类器 https://pypi.org/search/?c=Framework+%3A%3A+AsyncIO目前有 122 个图书馆,而框架 :: Trio 分类器 https://pypi.org/search/?c=Framework+%3A%3A+Trio只有 8。我希望这部分答案很快就会过时——例如,Kenneth Reitz 正在尝试在下一版本的 requests 中添加三重奏支持 https://twitter.com/kennethreitz/status/974963822682427393– 但现在,你应该预料到,如果你是三人组处理任何复杂的事情,那么你会遇到需要自己填写的缺失部分,而不是从 pypi 获取库,或者你需要使用trio-asyncio 包允许您在 trio 程序中使用 asyncio 库 https://trio-asyncio.readthedocs.io/. (The 三人聊天频道 https://gitter.im/python-trio/general对于了解可用的内容以及其他人正在做什么非常有用。)
Trio 让您的代码更简单
就实际的库而言,它们也有很大不同。 trio 的主要论点是,它使编写并发代码比使用 asyncio 简单得多。当然,你最后一次听到有人说他们的库让事情变得更难使用是什么时候......让我举一个具体的例子。在这次演讲 https://www.youtube.com/watch?v=i-R704I8ySE (slides https://github.com/python-trio/trio-talks/tree/master/njsmith-async-concurrency-for-mere-mortals),我使用实现的例子RFC 8305“快乐眼球” https://www.rfc-editor.org/rfc/rfc8305,这是一种简单的并发算法,用于有效地建立网络连接。这是一个东西Glyph https://stackoverflow.com/users/13564/glyph多年来一直在思考,他的 Twisted 最新版本大约有 600 行长。 (Asyncio 大致相同;Twisted 和 asyncio 在架构上非常相似。)在演讲中,我教您使用 trio 在
您可能还会发现用户的这些评论很有趣:1 https://github.com/python-trio/pytest-trio/issues/14#issuecomment-350454257, 2 https://github.com/python-trio/trio/issues/449#issuecomment-367796899, 3 https://gitter.im/python-trio/general?at=5ab8242f2b9dfdbc3a1fe9b1
细节上有很多很多差异
为什么会出现这种情况?这是一个更长的答案:-)。我正在逐渐致力于在博客文章和演讲中撰写不同的文章,并且我会尽力记住在链接可用时更新此答案。基本上,这可以归结为 Trio 拥有一小组精心设计的原语,这些原语与我所知道的任何其他库都有一些根本区别(当然,它们是建立在来自许多地方的想法的基础上)。以下是一些随机注释,可以给您一些想法:
asyncio 和相关库中一个非常非常常见的问题是您调用some_function()
,然后它返回,所以您认为它已经完成 - 但实际上它仍在后台运行。这会导致各种棘手的错误,因为它使得很难控制事情发生的顺序,或者知道事情何时真正完成,并且它可以直接隐藏问题,因为如果后台任务因未处理的异常而崩溃,asyncio 将通常只是将一些内容打印到控制台,然后继续。在 trio 中,我们通过“托儿所”处理任务生成的方式意味着这些事情都不会发生:当函数返回时,您就知道它已完成,并且 Trio 是目前唯一的 Python 并发库,其中异常始终会传播,直到您捕获它们。
Trio 管理超时和取消的方式很新颖,我认为比以前最先进的系统(如 C# 和 Golang)更好。事实上我确实写了一篇完整的文章 https://vorpus.org/blog/timeouts-and-cancellation-for-humans/所以我不会在这里详细讨论所有细节。但是 asyncio 的取消系统(或者说实际上是系统,它有两个语义略有不同的系统)基于比 C# 和 Golang 更古老的思想,并且很难正确使用。 (例如,代码很容易通过生成后台任务来意外“逃避”取消;请参阅上一段。)
有很多多余的东西stuff在 asyncio 中,可能会让人很难判断何时使用哪个东西 https://wiki.python.org/moin/TOOWTDI。你有 future、任务和协程,它们基本上都用于相同的目的,但你需要知道它们之间的区别。如果你想实现一个网络协议,你必须选择是使用协议/传输层还是流层,它们都有棘手的陷阱(这就是第一部分的内容)你链接的文章 https://vorpus.org/blog/some-thoughts-on-asynchronous-api-design-in-a-post-asyncawait-world/是关于)。
Trio 是目前唯一一个 Python 并发库,其中 control-C 按您期望的方式工作(即,它引发KeyboardInterrupt
无论您的代码在哪里)。这是一件小事,但意义重大:-)。由于各种原因,我认为这在 asyncio 中无法修复。
加起来
如果您需要下周将某些东西交付生产,那么您应该使用 asyncio(或 Twisted、Tornado 或 gevent,它们更加成熟)。他们拥有庞大的生态系统,其他人在你之前已经在生产中使用了它们,而且他们不会去任何地方。
如果尝试使用这些框架让您感到沮丧和困惑,或者如果想尝试不同的做事方式,那么一定要看看 trio - 我们很友好:-)。
如果你想在一年后将某些东西投入生产......那么我不知道该告诉你什么。 Python 并发性不断变化。 Trio 在设计层面有很多优势,但这足以克服 asyncio 的领先优势吗?标准库中的 asyncio 是优势还是劣势? (注意现在每个人都如何使用requests
,即使标准库有urllib https://docs.python.org/3/library/urllib.html.) trio 中有多少新想法可以添加到 asyncio 中?没人知道。我预计今年的 PyCon 上将会有很多有趣的讨论:-)。