在Python中计算对random的调用数?

在Python中计算对random的调用数?,python,random,python-3.x,Python,Random,Python 3.x,我有一个Python应用程序,我想在运行时监控对标准随机模块中函数的调用次数;有什么好方法可以做到这一点,或者我必须“手动”完成吗?制作一个包装函数,增加计数,然后进行调用并返回结果 如果你认为是“手册”,那么是的。 < P>我觉得Python探索者应该能够很好地完成它。看 在运行时,这似乎是一条路要走。当然,默认的随机模块没有decorators,因此可能需要使用decorators定义一个monitoredrandom模块,该decorator代理随机模块并统计调用。如果保持函数名和签名与随

我有一个Python应用程序,我想在运行时监控对标准随机模块中函数的调用次数;有什么好方法可以做到这一点,或者我必须“手动”完成吗?

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


如果你认为是“手册”,那么是的。

< P>我觉得Python探索者应该能够很好地完成它。看


在运行时,这似乎是一条路要走。当然,默认的随机模块没有decorators,因此可能需要使用decorators定义一个monitoredrandom模块,该decorator代理随机模块并统计调用。如果保持函数名和签名与随机中的相同,则只需修改代码中的导入即可。

下面是一个肮脏的解决方案:

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))

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

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}
0.000秒内调用7次函数
订购人:标准名称
ncalls tottime percall cumtime percall文件名:lineno(函数)
1    0.000    0.000    0.000    0.000 :1()
1 0.000 0.000 0.000 0.000巴。py:4(巴)
1 0.000 0.000 0.000 0.000 foo.py:4(foo)
1 0.000 0.000 0.000 0.000 my_模块。py:4(my_func)
1 0.000 0.000 0.000 0.000{方法'disable'的''lsprof.Profiler'对象}
2 0.000 0.000 0.000 0.000{随机对象的随机方法}
最后一行显示总共有2个对random方法的调用(在我的玩具示例中,它们位于两个不同的模块foo.py和bar.py中)


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

我能想到的最好方法是代理-我不相信用自定义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
一个可怕的混乱,但实际上是标准模块的代理。我真的不确定如何将其放入名称空间中-可能将其放入一个模块中,然后(立即命名)
从random\u testing import random
而不是普通的
import random


我注意到,通过这个方法运行两个
randint
会让我计算出六个-因此不完全确定内部如何工作….

您还可以对
random
模块进行猴子补丁,用包装器替换函数,以减少对代码库的影响。当然,除非他们出于某种原因需要以编程方式或在运行时访问此信息(当然,这将是问题中包含的重要信息),否则实际上,我需要在运行时监视此信息(我编辑了原始问题以反映这一点)。感谢+1!我将研究探查器代码,以进一步了解如何使用。曾经有一个PyMonitor项目使用垃圾收集器对Python程序进行运行时监控,但这是否符合您的目的还需要进一步研究。