未将部分异步功能检测为异步

时间:2018-09-20 10:22:09

标签: python python-asyncio

我有一个可以同时接受常规和异步功能的函数(不是协程,而是返回协程的函数)。

它在内部使用asyncio.iscoroutinefunction() test来查看它具有哪种类型的功能。

最近,当我尝试创建部分异步功能时,它崩溃了。

在此演示中,ptest 未被识别为协程函数,即使它返回协程,即ptest() 协程

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

问题原因很明显,但解决方案还不清楚。

如何动态创建通过测试的部分异步功能?

OR

如何测试partial object中包装的函子?

任何一个答案都可以解决问题。

2 个答案:

答案 0 :(得分:2)

您不能使partial()对象通过该测试,因为该测试要求将__code__对象直接附加到您传递给inspect.iscoroutinefunction()的对象上。

您应该改为测试partial包装的功能对象,可以通过[partial.func属性[[https://docs.python.org/3/library/functools.html#functools.partial.func)进行访问:

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

如果您还需要测试partial()个对象,请针对functools.partial进行测试:

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

答案 1 :(得分:1)

我通过用 partial 替换所有 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