如何判断一个函数或方法是普通函数还是异步函数?我希望我的代码能自动支持正常或异步回调,并需要一种方法来测试传递的函数类型。
async def exampleAsyncCb():
pass
def exampleNomralCb():
pass
def isAsync(someFunc):
#do cool dynamic python stuff on the function
return True/False
async def callCallback(cb, arg):
if isAsync(cb):
await cb(arg)
else:
cb(arg)
根据传递的函数类型,它应该正常运行或使用await。我尝试了各种方法,但不知道如何实现isAsync()
。
8条答案
按热度按时间rks48beu1#
使用Python的inspect模块。
inspect.iscoroutinefunction(object)
如果对象是协程函数(用async def语法定义的函数),则返回true。
这个函数从Python 3.5开始就可用了。该模块可用于Python 2,但功能较少,并且肯定没有您正在寻找的功能:inspect
顾名思义,Inspect模块对检查很多东西很有用。文件上说
inspect模块提供了几个有用的函数来帮助获取有关活动对象的信息,如模块、类、方法、函数、追溯、框架对象和代码对象。例如,它可以帮助您检查类的内容,检索方法的源代码,提取和格式化函数的参数列表,或获取显示详细追溯所需的所有信息。
此模块提供的服务主要有四种:类型检查、获取源代码、检查类和函数以及检查解释器堆栈。
此模块的一些基本功能包括:
它还包含检索源代码的功能
方法是直观地命名的。如有需要,可在文档中找到说明。
jw5wzhpr2#
如果您不想使用
inspect
引入另一个导入,iscoroutine
也可以在asyncio
中使用。z3yyvxxp3#
TLDR
如果你想检查某个东西应该和
await
一起使用,使用inspect.isawaitable
(当你测试某个东西是callable()
而不仅仅是一个函数时)。与
iscoroutine
或iscoroutinefunction
不同,它也适用于Future
和实现__await__
方法的对象。详细信息
上面的解决方案将适用于简单的情况,当你传递协程函数时。在某些情况下,您可能希望传递 awaitable object 函数,它的行为类似于协程函数,但不是协程函数。两个例子是Future类或 Future-like object 类(实现
__await__
魔术方法的类)。在这种情况下,iscoroutinefunction
将返回False
,这是你不需要的。在非异步的例子中,传递非函数的callable作为callback更容易理解:
回到async世界,类似的情况:
解决方法不是使用
iscoroutine
或iscoroutinefunction
,而是使用inspect.isawaitable
。它与就绪对象一起工作,因此您必须首先创建它。换句话说,我建议使用的解决方案:这是更普遍的(我确信逻辑上是正确的)解决方案。
v64noz0r4#
协同例程设置了
COROUTINE
标志,代码标志中的第7位:值128作为常量存储在
inspect
模块中:inspect.iscoroutinefunction()
函数就是这样做的;测试对象是否是函数或方法(以确保存在__code__
属性)并测试该标志。参见源代码。当然,使用
inspect.iscoroutinefunction()
是可读性最好的,并且可以保证在代码标志发生变化时继续工作:lmyy7pcs5#
扩展上面的答案。自Python 3.6以来,有4种类型的函数:
如果您的应用程序不知道给定函数的类型,它可能是上述函数之一,异步函数可能是协程函数或异步生成器函数。
asyncio.iscoroutinefunction(someFunc)
只检查一个函数是否是协程函数,对于异步生成器,可以使用inspect.isasyncgenfunction()
。示例代码如下所示:nwlqm0z16#
我在这里找不到其他答案来满足这个要求。至少在py 3.10中:
相反,为了测试你可以做:
请注意:
在我自己的代码中,我曾经有很多:
一个更清晰的模式,你想处理任何一个可能是:
可能存在上述的许多不同变型。
oxcyiej77#
如何在这里应用EAFP:
这也解决了当cb也是partial的instance时的问题
已知限制:
qc6wkl3g8#
asyncio.iscoroutine()
用于判断协程,asyncio.isfuture()
用于判断任务或将来