从同步代码重新输入异步事件循环

greenback的Python项目详细描述


Latest PyPI versionDocumentation statusAutomated test statusTest coverageCode style: blackChecked with mypy

Python3.5引入了async/await语法来定义 在协同多任务处理中可以并发运行的函数 框架,如asyncioTrio。这种框架有许多优点 与以前的并发方法相比:它们的扩展性比线程好 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 了解详情。在

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

推荐PyPI第三方库


热门话题
javapojo到org。布森。文件,反之亦然   java突然增加了G1老一代的承诺内存,减少了Eden的大小   java为什么对多个RXJava观察对象不执行并行执行?   java中的枚举是故障安全的吗?如果是,怎么做?   java是等待字符串变为相等的正确方法   java CodeAbbey挑战14个数据输入问题?   在java中的任意位置插入。util。列表   java替换html中的值   java需要帮助破译一个小堆栈跟踪:我使用的是哪种WS?   java Guice依赖项注入器空指针异常   java如何在3D引擎中实现视图剪裁平面?   JavaEclipseRCP:操作与命令需要更新   java如何使用XPAGES DesignerFacesServlet显示泰语字母(以及另一个亚洲/阿拉伯字母)   java装饰器模式问题   java我对空间复杂性的分析正确吗?   不显示java OpenGL ES 2纹理   使用java问题中的wc命令计算行数   java为什么空指针异常取决于条件的顺序?   Java日期在同一天或同一个月   java在使用lambda表达式时在变量中存储一些值