3

実行時に、標準のランダム モジュールの関数の呼び出し数を監視したい Python アプリケーションがあります。これを行う良い方法はありますか、それとも「手動で」行う必要がありますか?

4

5 に答える 5

7

It seems to me that Python profiler should be able to do it "nicely". Look at a post about Python profiling on SO.

At runtime, it seems that the decorators are the way to go. Of course, the default random module does not have the decorators, so perhaps you need to define a monitoredrandom module with decorators that proxys the random module and counts the calls. If you keep the function names and signatures the same as in random, you only have to modify the imports in your code.

于 2012-06-24T14:18:51.817 に答える
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))

このコードは、インポートを含む他のコードの前に、プログラムの最初に実行する必要があります (別のモジュールにすることができます)。

于 2012-06-24T14:24:06.633 に答える
3

カウントをインクリメントして呼び出しを行い、結果を返すラッパー関数を作成します。

それを「手動」と考えるなら、そうです。

于 2012-06-24T14:16:13.873 に答える
2

私が考えることができる最善の方法はプロキシです-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

恐ろしいクラッジですが、事実上、標準モジュールへのプロキシです。それを名前空間に入れる方法はよくわかりません-おそらくそれをモジュールに入れてからfrom random_testing import random、通常のimport random.

randintこのメソッドを使用して 2 つ実行すると、カウントが 6 になることに気付きました。

于 2012-06-24T14:56:28.103 に答える
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}

最後の行は、全体的に random メソッドへの 2 つの呼び出しがあったことを示しています (私のおもちゃの例では、foo.py と bar.py の 2 つの異なるモジュールにありました)。

編集:もちろん、コメントで指摘されているように、これはカウントをオフラインにしたい場合にのみ役立ちます。

于 2012-06-24T14:24:17.210 に答える