从同步代码重新输入异步事件循环
greenback的Python项目详细描述
Python3.5引入了async/await语法来定义 在协同多任务处理中可以并发运行的函数 框架,如asyncio或Trio。这种框架有许多优点 与以前的并发方法相比:它们的扩展性比线程好 clearer about control flow 而不是gevent提供的隐式协同多任务处理。他们也在 积极开发以探索一些exciting new ideas about concurrent programming。在
将现有的代码库移植到async/await语法可以是 不过,这很有挑战性,因为它有点“病毒式”:只有异步 函数可以调用另一个异步函数。这意味着你不只是 要修改实际执行I/O的函数,还需要 (琐碎地)修改每个直接或间接调用 执行I/O的函数,而结果通常是一种改进 (“显式胜于隐式”),一大步走到这一步并非如此 总是可行的。在
greenback是一个试图弥合这一差距的小型库。它 允许您从语法上将回调到异步代码中 同步函数,只要同步函数 从一个异步IO或一个异步IO开始 事件循环)设置greenback蹦床 下面。这样,您就可以将程序迁移到async/await 语法一次一层,而不是一次全部。在
greenback需要Python3.6或更高版本以及 支持greenlet库。CPython或PyPy都可以。 没有已知的操作系统依赖项。在
快速启动
- 在将要执行的每个任务中至少调用一次await greenback.ensure_portal() 使用greenback。(同一任务中的其他调用不起任何作用)你可以思考 创建一个门户,将来调用 greenback.await_()在同一个任务中。在
- 稍后,使用greenback.await_(foo())作为 await foo()放在你不能写await的地方。在
- 有关更多详细信息和其他辅助方法,请参见 documentation。在
示例
假设您从这个不知道异步的程序开始:
import subprocess def main(): print_fact(10) def print_fact(n, mult=1): """Print the value of *n* factorial times *mult*.""" if n <= 1: print_value(mult) else: print_fact(n - 1, mult * n) def print_value(n): """Print the value *n* in an unreasonably convoluted way.""" assert isinstance(n, int) subprocess.run(f"echo {n}", shell=True) if __name__ == "__main__": main()
使用greenback,可以通过以下方式将其更改为在Trio事件循环中运行 只更改顶层和底层,不更改print_fact()。在
^{pr2}$常见问题解答
为什么叫“美元”?它使用greenlet库来获取 back到封闭的异步上下文。另外,也许它可以节省你money(工程时间)或者 什么。在
它是如何工作的?运行^{tt13}之后$ 在某个任务中,该任务的每一步都将在一个greenlet中运行。 (这是通过在事件之间插入一个“垫片”协程来实现的 循环和任务的协同程序;有关详细信息,请参阅源代码。) 对greenback.await_()的调用就可以从该greenlet切换 回到父代greenlet,它可以很容易地执行必要的操作 await,因为它可以直接访问异步环境。这个 然后每个任务步骤greenlet将使用值或异常恢复 由await生成。在
在生产中我应该相信这个吗?也许吧;试试看。这个 技术在某些方面是一个可怕的黑客,而且有一些表现 含义(任何调用await greenback.ensure_portal()的任务都将运行得稍慢)。greenback 它本身是一个相当少量的纯Python代码 greenlet。(有一个相当安全的ctypes黑客攻击是必要的 处理一个不受异步加速影响的旋钮 CPython上的扩展模块)greenlet是一个充满神秘色彩的C模块 平台特定的黑客攻击,但它已经存在很长时间了 流行的生产质量并发系统,如geventrelay 很严重。在
什么不起作用?
- Greenlet交换的工作原理是将C堆栈的部分移动到不同的 内存地址,依赖于Python对象是 完全堆分配,不包含任何指向C的指针 堆栈。性能不佳的C扩展模块可能会违反这一点 如果与greenback一起使用,则可能会崩溃。 这样的扩展模块是有缺陷的,如果没有扩展模块就可能崩溃 greenback,但可能只是在一个模糊或不太可能 一系列操作。在
- 在终结器(^{tt33})内调用greenback.await_()$ 方法)、信号处理程序或weakref回调不受支持。它 可能大部分时间都可以工作,甚至可以一直工作,但是 这种方法运行的环境非常奇怪 作者不准备作任何保证。(不是你的 剩下的部分有什么保证,只是一些更好的理论 接地。)
许可证
greenback根据您选择的MIT或apache2.0许可证进行授权。 见LICENSE 了解详情。在
- 项目
标签: