LoginSignup
2
2

More than 5 years have passed since last update.

python で実行時間を計るアノテーションを作る

Posted at

欲しくなったときに毎回作ってるので、書いて放り投げておく。

精度はそんなこだわって無くて、どっちかと言うと使いやすさに気を使ってみた。

デコレータ作っちゃおうぜ

計測したいメソッドの中や前後にうろちょろデバッグ処理書くのは見通しが悪くなるので、@measureとか作ってみる。

def measure(label, times):
    def _measure(func):
        def wrapper(*args):
            print label
            for x in xrange(1, 1 + times):
                t1 = time() * 1000
                result = func(*args)
                t2 = time() * 1000
                print '  %02d: %d msec' % (x, (t2 - t1))
            return result
        return wrapper
    return _measure

こんなのをどっかに置いといて、

from time import sleep

@measure(label = 'foo 1', times = 3)
def foo(n, s):
    sleep(0.5)
    return 'n: %(n)d, s: %(s)s' % locals()

こんな感じでアノテートする。
そうするとこんな感じに指定回数実行されて、本来の戻り値が返される。

>>> print foo(3, 5)

foo 1
  01: 500 msec
  02: 500 msec
  03: 500 msec
n: 3, s: 5

こんだけ。

絶対にもっとちゃんとしたのがあるけど、ライブラリ入れてちゃんと計るほどでもない自分のおもちゃに対してとかは、十分役に立つしコードを汚さないので良い感じ。

デコレータ補足

python のデコレータは関数渡しさえ知っていれば、一度理解してしまえば案外難しくない。
これは@measureが引数を取れるためにmeasureの下に_measureを置いているのがちょっと複雑に見えるけど、
要は@measure(label = 'foo 1', times = 3)が終わったときにfuncを受ける関数が返れば良いだけ。

デコレータは装飾している関数を引数に取れば良いので、そこを気にしていれば多分大丈夫。
沢山良い記事があるのでデコレータについては割愛するけど、以下の最低機能の形を理解すればあとは書いたり調べたりは応用が利くはず。

def simple_measure(func):
    def wrapper():
        print 'start'
        func()
        print 'end'
    return wrapper
@simple_measure
def simple_foo():
    print 'simple_foo'
>>> simple_foo()

start
simple_foo
end

おしまい。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2