计算Python中随机调用的次数?

时间:2012-06-24 14:09:44

标签: python random python-3.x

我有一个Python应用程序,我希望在运行时监视标准随机模块中函数的调用次数;有什么好方法可以做到这一点,还是我必须“手动”做到这一点?

5 个答案:

答案 0 :(得分:7)

在我看来,Python分析器应该能够“很好地”完成它。请看a post about Python profiling on SO

在运行时,似乎decorators是可行的方法。当然,默认随机模块没有装饰器,因此您可能需要定义带有装饰器的monitoredrandom模块,这些装饰器代理随机模块并对调用进行计数。如果保持函数名称和签名与随机相同,则只需修改代码中的导入。

答案 1 :(得分:4)

这是一个肮脏的解决方案:

import functools

def monitor(f):
    @functools.wraps(f)
    def decorated(*args, **kwargs):
        print("{}: {}, {}".format(f.__name__, args, kwargs))
        # Do whatever you want: increment some counter, etc.
        return f(*args, **kwargs)
    return decorated

import random

for name in dir(random):
    f = getattr(random, name)
    if callable(f) and not name.startswith('_'):
        setattr(random, name, monitor(f))

此代码应在程序的最开始执行(可以在单独的模块中),在任何其他代码之前执行,包括导入。

答案 2 :(得分:3)

创建一个包装函数,增加计数,然后进行调用并返回结果。

如果您考虑“手动”,那么是。

答案 3 :(得分:2)

我能想到的最好的是代理 - 我不相信用自定义的dict-esque对象替换sys.modules是可能的。注意我不喜欢这个,而且你自己就是这样......

class random(object):
    def __init__(self):
        from collections import defaultdict
        import random as r_
        self.R = r_
        self.__lookups = defaultdict(int)
        def __getattr__(self, name):
            self.__lookups[name] += 1
            return getattr(self.R, name)
    @property
    def freq(self):
        return self.__lookups

可怕的kludge但实际上是标准模块的代理。如何将它放入命名空间我真的不确定 - 也许把它放在一个模块中,然后(现在建立名称)from random_testing import random而不是正常的import random

我注意到通过这种方法运行两个randint给了我六个计数 - 所以不完全确定内部是如何在那里工作的....

答案 4 :(得分:1)

cProfile返回每个函数的调用次数。

这样的事情应该有效:

import my_module
import cProfile

cProfile.run('my_module.my_func()')

其中my_module.my_func是程序的入口点。这输出如下:

     7 function calls in 0.000 seconds

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.000    0.000    0.000    0.000 <string>:1(<module>)
     1    0.000    0.000    0.000    0.000 bar.py:4(bar)
     1    0.000    0.000    0.000    0.000 foo.py:4(foo)
     1    0.000    0.000    0.000    0.000 my_module.py:4(my_func)
     1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
     2    0.000    0.000    0.000    0.000 {method 'random' of '_random.Random' objects}

最后一行显示总共有2次调用随机方法(在我的玩具示例中有两个不同的模块,foo.py和bar.py)。

编辑:当然,这只有在您希望计数离线时才有用,正如评论中所指出的那样。