我想在python中编写一个方法,它动态地读取一个模块并创建该模块中所有函数的列表。然后我想循环遍历此列表并调用每个函数。到目前为止,我有以下代码:
import mymodule
from inspect import getmembers, isfunction
def call_the_functions():
functions_list = [f for f in getmembers(mymodule) if isfunction(f[1])]
for f in functions_list:
result = f()
我的问题是我的程序崩溃了,因为某些函数需要参数。我想做类似以下的事情,但不知道如何:
for f in functions_list:
args = [""] * f.expectedNumberOfArguments()
result = f(*args)
我是以正确的方式来做这件事的吗? (我基本上是在编写一个单元测试,第一个检查只是函数返回一个正确类型的对象,不管它们被调用的参数如何。)
答案 0 :(得分:3)
您可以使用inspect.getargspec()
:
In [17]: def f(x, z=2, *args, **kwargs): pass
In [18]: inspect.getargspec(f)
Out[18]: ArgSpec(args=['x', 'z'], varargs='args', keywords='kwargs', defaults=(2,))
调用与任意参数无关的函数是否有意义是一个不同的问题......
答案 1 :(得分:3)
您的方法存在根本缺陷。如果仔细写,函数将通过引发TypeError
或断言来拒绝无效类型的参数。如果做不到这一点,他们会尝试访问参数上的属性或方法,并立即获得AttributeError
。
试图避免编写能够了解被测函数的单元测试是徒劳的。
答案 2 :(得分:1)
您可以使用inspect
模块和getargspec
。这是一个简单的例子:
import inspect
def myfunc(x):
return x * 2
print inspect.getargspec(myfunc);
给出:
ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)
某些函数可能是生成器,因此调用它们的测试策略可能无法满足您的期望,inspect.isgeneratorfunction()
将允许您对其进行测试。