Python中标准函数自动转换为异步函数

问题描述 投票:0回答:2

在我编写的大多数异步协程中,我只需要替换函数定义

def func()
->
async def func()
和 sleep
time.sleep(s)
->
await asyncio.sleep(s)

是否可以将标准Python函数转换为异步函数,其中所有

time.sleep(s)
都转换为
await asyncio.sleep(s)

示例

任务期间的表现
衡量任务期间的表现

import asyncio
import random

async def performance_during_task(task):
    stop_event = asyncio.Event()

    target_task = asyncio.create_task(task(stop_event))
    perf_task = asyncio.create_task(measure_performance(stop_event))

    await target_task
    await perf_task

async def measure_performance(event):
    while not event.is_set():
        print('Performance: ', random.random())
        await asyncio.sleep(.2)

if __name__ == "__main__":
    asyncio.run(
        performance_during_task(task)
    )

任务
任务必须用

async def
await asyncio.sleep(s)

定义
async def task(event):
    for i in range(10):
        print('Step: ', i)
        await asyncio.sleep(.2)
    
    event.set()

进入->

简单的任务定义
让其他人不用担心异步等问题。我希望他们能够正常定义任务(例如使用装饰器?)

@as_async
def easy_task(event):
    for i in range(10):
        print('Step: ', i)
        time.sleep(.2)
    
    event.set()

这样它就可以用作异步函数,例如

performance_during_task()

python asynchronous python-asyncio python-decorators
2个回答
1
投票

我想我找到了一个类似于评论中提到的有趣的 GitHub 示例的解决方案以及类似的帖子here

我们可以写一个装饰器就像

from functools import wraps, partial


def to_async(func):
    @wraps(func)  # Makes sure that function is returned for e.g. func.__name__ etc.
    async def run(*args, loop=None, executor=None, **kwargs):
        if loop is None:
            loop = asyncio.get_event_loop(). # Make event loop of nothing exists
        pfunc = partial(func, *args, **kwargs)  # Return function with variables (event) filled in
        return await loop.run_in_executor(executor, pfunc).
    return run

这样简单的任务就变成了

@to_async
def easy_task(event):
    for i in range(10):
        print('Step: ', i)
        time.sleep(.2)
    
    event.set()

其中 wraps 确保我们可以调用原始函数的属性(在此处解释)。

并且 partial 填写变量,如here所述。


0
投票

有一个现成的包可以做到这一点。这叫

awaits

安装:

pip install awaits

并按如下所示使用它:

import asyncio
from awaits import awaitable

@awaitable
def sum(a, b):
  return a + b

print(asyncio.run(sum(2, 2)))

在这个例子中,我们将一个常规函数变成了一个协程函数。

© www.soinside.com 2019 - 2024. All rights reserved.