Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

partial asynchronous functions are not detected as asynchronous

I have a function which accepts both regular and asynchronous functions (not coroutines, but functions returning coroutines).

Internally it uses asyncio.iscoroutinefunction() test to see which type of function it got.

Recently it broke down when I attempted to create a partial async function.

In this demonstration, ptest is not recognized as a couroutine function, even if it returns a coroutine, i.e. ptest() is a coroutine.

import asyncio
import functools

async def test(arg): pass
print(asyncio.iscoroutinefunction(test))    # True

ptest = functools.partial(test, None)
print(asyncio.iscoroutinefunction(ptest))   # False!!

print(asyncio.iscoroutine(ptest()))         # True

The problem cause is clear, but the solution is not.

How to dynamically create a partial async func which passes the test?

OR

How to test the func wrapped inside a partial object?

Either answer would solve the problem.

like image 686
VPfB Avatar asked Sep 20 '18 10:09

VPfB


People also ask

What are asynchronous user-defined functions?

Asynchronous user-defined functions must keep track of a handle and use that handle when informing Excel that the function call is finished. An asynchronous user-defined function is split into two pieces. The first piece is the standard UDF entry point, which will launch a second, separate asynchronous operation.

How do you handle asynchronous errors in JavaScript?

Handling Asynchronous Function Errors First of all, there are two common ways in creating an asynchronous function. The first one is by using Promise and second one is using async-await. A catch () function will be executed if either the promise rejects or an async function throws an error.

How do you test an async function without blocking the application?

This without blocking the application. Because Async functions can only be declared at the top level or inside a block, the correct way to test this in your browser’s console is as follows: Enter this.waitAndInform (); to test the async function.

What are async functions in JavaScript?

Async functions should not be confused with asynchronous loading of UI5 components. Also, the fact that async functions enable us to call functions synchronous works confusing. In this blog I show in detail how to use async functions. Async functions are part of version 8 of JavaScript a.k.a. EcmaScript8, ES8 or ES2017.


Video Answer


2 Answers

Using Python versions < 3.8 you can't make a partial() object pass that test, because the test requires there to be a __code__ object attached directly to the object you pass to inspect.iscoroutinefunction().

You should instead test the function object that partial wraps, accessible via the partial.func attribute:

>>> asyncio.iscoroutinefunction(ptest.func)
True

If you also need to test for partial() objects, then test against functools.partial:

def iscoroutinefunction_or_partial(object):
    while isinstance(object, functools.partial):
        object = object.func
    return inspect.iscoroutinefunction(object)

In Python 3.8 (and newer), the relevant code in the inspect module (that asyncio.iscoroutinefunction() delegates to) was updated to handle partial() objects, and you no longer have to unwrap partial() objects yourself. The implementation uses the same while isinstance(..., functools.partial) loop.

like image 138
Martijn Pieters Avatar answered Oct 14 '22 21:10

Martijn Pieters


I solved this by replacing all instances of partial with async_partial:

def async_partial(f, *args):
   async def f2(*args2):
       result = f(*args, *args2)
       if asyncio.iscoroutinefunction(f):
           result = await result
       return result

   return f2
like image 28
serg06 Avatar answered Oct 14 '22 22:10

serg06