【问题标题】:Write an async coroutine that's python 2 and 3 compatible编写一个兼容 python 2 和 3 的异步协程
【发布时间】:2019-01-03 13:13:44
【问题描述】:

通常要编写兼容 python 2/3 的代码,您需要遵循两种解释器都可以理解的特定风格,例如:https://python-future.org/compatible_idioms.html

但是,由于 asyncio 引入了 async defawait function() 等语法,如果在 Python 2 下运行会导致解析错误。

如何编写一个与 python 2 和 python 3 兼容的库,并且仍然可以提供 asyncio 接口?如果没有简单的方法可以做到这一点,是否可以在库中制作某个只能在 python 3.5+ 中导入的异步子模块?

【问题讨论】:

  • 您是否有任何特定的理由来支持旧版 Python(生命周期结束后不到一年 pythonclock.org)。我可能不会使用 Python 2 和 Python
  • 如果您确实想支持旧版本,则必须避免使用 async/await 并使用 threading/eventlet 或使用 generators/yield 语句实现异步协程。
  • 不是针对新库,是针对支持2&3的现有库。但无论如何,对于想要支持任何版本的 Python 3 的库来说,问题仍然存在。
  • 不推荐使用异步生成器吗?它们在 Python 3 的未来版本中仍然有效吗?如果是这样,您介意写一个答案吗,因为这可能是我的解决方案
  • 异步生成器仅在 Python 3.6 及更高版本中可用,并且绝对不会被弃用。普通生成器在 Python 2 和 3 中都可用,并且也没有被弃用。不推荐使用生成器来实现协程,即@asyncio.coroutine 装饰器。但即使是那种生成器也严重依赖于 yield from 关键字和 asyncio 框架,而这两者在 Python 2 中都没有。

标签: python python-3.x asynchronous python-asyncio


【解决方案1】:

在 Python 2 中支持异步风格的协程是不可能的,因为 Python 2 没有:

  • async defawait;
  • 他们的前任yield from;
  • 异步库本身,任何形状或形式。

有一个项目是使用没有yield from 的普通生成器创建 Python 2 版本的 asyncio,但它是在几年前的 abandoned

【讨论】:

  • 那么,我的第二个问题呢:“是否可以在库中制作某个只能在 python 3.5+ 中导入的异步子模块?”
  • @Miguel 当然,异步子模块并没有什么神奇之处。
【解决方案2】:

虽然在 Python 2 中支持 async def 函数是不可行的,但可能创建一个包含仅在 Python 3.5 或更高版本中导入的 async def 函数的模块。但! 可能有更好的方法来解决这个问题,例如将 asyncio 代码放在不同的模块、包或完全独立的库中。

下面的示例完全属于“是的你可以,但你为什么要这样做?”的简单测试表明它可以在 CPython 2.6.9 上运行3.7.3,仅在 3.5 或更高版本上加载 asyncio 代码。

from __future__ import print_function
import sys


ASYNC_SOURCE = """
import asyncio

async def three():
    print('three') 
"""
if sys.version_info[0] > 2 and sys.version_info[1] > 4:
    exec(compile(ASYNC_SOURCE, __file__, "exec"))


def two():
    print("two")


if __name__ == "__main__":
    two()
    if "three" in locals():
        asyncio.run(three())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-11
    • 1970-01-01
    • 2017-06-25
    • 2017-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多