异步函数完成后的Python调用回调

时间:2019-03-05 13:17:07

标签: python python-asyncio

异步函数运行完毕后,我正在尝试调用回调

这是我想做的事的一个例子:

import asyncio

async def asyncfunction():
    print('Hello')
    await asyncio.sleep(10)
    print('World')
    return 10

def callback(n):
    print(f'The async function returned: {n}')

loop = asyncio.get_event_loop()

# Will block the print until everything is done
callback(loop.run_until_complete(asyncfunction()))
print('Hey')

这是做什么的

Hello
World
The async function returned: 10
Hey

这就是我想要的事情
编辑:“嘿”的位置并不重要,只要它不必等待异步功能完成

Hello
Hey
World
The async function returned: 10

编辑:经过一些测试,我发现了一种可以实现自己想要的方式,尽管我不知道这是否是最好的方式

import asyncio
import threading

async def asyncfunction():
    print('Hello')
    await asyncio.sleep(10)
    print('World')
    return 10

def callback(n):
    print(f'The async function returned: {n}')

def wrapper(loop):
    callback(loop.run_until_complete(asyncfunction()))

loop = asyncio.get_event_loop()
thr = threading.Thread(target=wrapper,args=(loop,))
thr.start()
print('Hey')

3 个答案:

答案 0 :(得分:3)

免责声明:Following code creates different threads for each function.

这在某些情况下可能很有用,因为它更易于使用。但要知道它不是异步的,而是使用多线程产生异步的错觉,即使装饰者建议这样做。

要使任何函数非阻塞,只需复制装饰器并使用回调函数作为参数装饰任何函数。回调函数会接收函数返回的数据。

import asyncio
import requests


def run_async(callback):
    def inner(func):
        def wrapper(*args, **kwargs):
            def __exec():
                out = func(*args, **kwargs)
                callback(out)
                return out

            return asyncio.get_event_loop().run_in_executor(None, __exec)

        return wrapper

    return inner


def _callback(*args):
    print(args)


# Must provide a callback function, callback func will be executed after the func completes execution !!
@run_async(_callback)
def get(url):
    return requests.get(url)


get("https://google.com")
print("Non blocking code ran !!")

答案 1 :(得分:1)

要获得该命令,您需要在print('Hey')之后继续执行协程。您还需要在'Hey'休眠时在{lull”中打印asyncfunction。这基本上只能由事件循环本身来调度;因为asyncfunction是您所知道的所有信息的黑匣子,并且您不知道它在等待什么,或者为什么或在它处于休眠状态时可以从中明确地获得控制权。

因此,将asyncfunctionprint('Hey')都作为异步任务执行,并且希望主要执行计划,以使“ Hey”计划在{{1 }}正在睡觉。

asyncfunction

val, *_ = loop.run_until_complete(asyncio.gather( asyncfunction(), asyncio.coroutine(print)('Hey') )) callback(val) asyncio.coroutine(print)转换为print函数,并且async在事件循环上同时安排两个时间,并且可能 gather将在print处于休眠状态时执行。

答案 2 :(得分:0)

将线程与asyncio一起使用只是令人困惑,而且很可能不是您想要的。 run_until_complete是阻塞调用之一,可能应该是asyncio程序中的最后一条语句。

要在调用异步函数后添加代码,只需创建一个包装器

async def myfunc():
  n = await asyncfunction()
  callback(n)

loop.run_until_complete(myfunc()) # from python 3.7, asyncio.run(myfunc())

如果您只想安排一些代码异步运行并继续执行其他操作,请创建一个任务并等待最后

async def a_main():
  task = asyncio.ensure_future(myfunc()) # from python 3.7, asyncio.create_task(...)
  print("Hey")
  # Anything else to run
  await task # wait for the task to complete

loop.run_until_complete(a_main())