Python 模块“asyncio”没有属性“to_thread”

abr*_*uez 9 python concurrency multithreading python-asyncio

来自 python 的 asyncio 示例:

import asyncio
import time
def blocking_io():
    print(f"start blocking_io at {time.strftime('%X')}")
    # Note that time.sleep() can be replaced with any blocking
    # IO-bound operation, such as file operations.
    time.sleep(1)
    print(f"blocking_io complete at {time.strftime('%X')}")

async def main():
    print(f"started main at {time.strftime('%X')}")

    await asyncio.gather(
        asyncio.to_thread(blocking_io),
        asyncio.sleep(1))

    print(f"finished main at {time.strftime('%X')}")


asyncio.run(main())

# Expected output:
#
# started main at 19:50:53
# start blocking_io at 19:50:53
# blocking_io complete at 19:50:54
# finished main at 19:50:54
Run Code Online (Sandbox Code Playgroud)

它正在输出下一个错误:

    asyncio.to_thread(blocking_io),
    AttributeError: module 'asyncio' has no attribute 'to_thread'
Run Code Online (Sandbox Code Playgroud)

此功能已被弃用吗?使用 asyncio 进行线程化的替代方案是什么?

Bec*_*hma 17

to_thread仅适用于 python 3.9+,如果您使用的是 python 3.8 或更早版本,您可以复制它的源代码:

async def to_thread(func, /, *args, **kwargs):
    loop = asyncio.get_running_loop()
    ctx = contextvars.copy_context()
    func_call = functools.partial(ctx.run, func, *args, **kwargs)
    return await loop.run_in_executor(None, func_call)
Run Code Online (Sandbox Code Playgroud)

此方法将上下文复制到线程(以使用您设置的ContextVars的当前值)

如果您不需要它而只想要一个内衬:

await asyncio.get_running_loop().run_in_executor(None, blocking_io, arg1, arg2)
Run Code Online (Sandbox Code Playgroud)

有关run_in_executor的更多信息