2021年3月11日星期四

Decorators to async functions python

I am trying to test a function and looks like the async call fails in the way this is written.

    import asyncio      import inspect         def foo(*args, **kwargs):          print("function wrapped")           def wrapper_1(func):              print('enter wrapper_1')              async def wrapper(func):                  print('wrapped function called')                  if inspect.iscoroutinefunction(func):                      data=await func(*args, **kwargs)                  else:                      data=func(*args, **kwargs)                  if data==3:                      print('PASS')                  else:                      print('FAIL')                  return func              return wrapper              return wrapper_1        @foo(x=1, y=2)      async def sum1(x,y):          await asyncio.sleep(5)          return sum([x+y])        @foo(x=1, y=2)      def sum2(x,y):          return sum([x+y])  

I am trying to use the same function for both the functions below. I was expecting a result something like: for both the ones below.

    function wrapped      enter wrapper_1      wrapped function called      PASS  

Instead it prints only

    function wrapped      enter wrapper_1  

It doesnt enter the wrapper function. I get an error:

    RuntimeWarning: coroutine 'foo.<locals>.wrapper' was never awaited  

Any idea where did I go wrong. Or in general, making sure the below code works without the use of asyncio.run or loop.run_until_complete would also do the job.

I know the following function would work. But the problem is that i cant run it in an existing event loop. So, neither of asyncio.run or loop.run_until_complete would work.

def foo(*args, **kwargs):      print("function wrapped")       def wrapper(func):          print('wrapped function called')          if inspect.iscoroutinefunction(func):              data=asyncio.run(func(*args, **kwargs))          else:              data=func(*args, **kwargs)          if data==3:              print('PASS')          else:              print('FAIL')          return func      return wrapper    @foo(x=1, y=2)  async def sum1(x,y):      await asyncio.sleep(5)      return sum([x+y])    @foo(x=1, y=2)  def sum2(x,y):      return sum([x+y])  

This would print

function wrapped  wrapped function called  PASS  

Edit: I have the following conditions:

  1. x,y are just some random arguments i have for the purpose of generalisation. But there could be close to 100 variables that i would have. Its better to retain the *args,**kwargs in the first line.
  2. I would need the print to happen when i execute the code that i wrote above and not when another main is written.
  3. Instead of writing await, i could have written asyncio.run(func(*args,**kwargs)) in my code to get the result but the problem is that i cant run it in an existing event loop. We might want to be able to run this on a server. So i cant use either of the two functions from nest-asyncio.
https://stackoverflow.com/questions/66579405/decorators-to-async-functions-python March 11, 2021 at 05:08PM

没有评论:

发表评论