challenge メソッドのフック

例えば、あるクラスのあるメソッドを実行する前に他の処理を呼びたい(例えばログやトランザクション開始など)。 また、そのメソッドの終了後にも何らかの後処理を呼びたい(トランザクション終了など)。

そのような、メソッドに対するフック処理を書いてください。 ライブラリを使用してメソッドのフックを実現した場合は ライブラリの名前を紹介してくれると助かります。

Posted feedbacks - Python

メソッド限定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Hoge(object):
    def process(self):
        print 'Hoge::process'

class HogeHook(Hoge):
    def process(self):
        print 'begin HogeHook::process'
        super(HogeHook, self).process()
        print 'end HogeHook::process'

Hoge = HogeHook

a = Hoge()
a.process()

decoratorを使ってmultithreadでクリティカルセクションを守るコードです。try/finallyを使っているのでlockのreleaseもれもないはずです。 accessorでどのようにlockにアクセスするか指定できます。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def synchronized_with(accessor):
  def bind(critical_section):
    def synchronized(self, *args, **kw):
      lock = accessor(self, *args, **kw)
      lock.acquire()
      try:
        ret = critical_section(self, *args, **kw)
      finally:
        lock.release()
      return ret
    return synchronized
  return bind

デコレータを使って。トランザクションとのことなので、一応例外が出ても "after" が表示されることを確認。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
def test(f):
    def wrap(*a, **kw):
        print "before"
        try:
            return f(*a, **kw)
        finally:
            print "after"
    return wrap

class Foo:
    @test
    def foo(self, x, exc=False):
        print x
        if exc:
            raise RuntimeError("foo")

if __name__ == '__main__':
    Foo().foo(3)
    Foo().foo(4, exc=True)

どう使うかを追加。でないとpythonのdecoratorをしらない人に不親切すぎ。

fooの中身がlock不要に見えるのは気にしないでください。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import threading

class class_level_lock:
  _lock = threading.RLock()
  lock = lambda self, *args, **kw : self._lock

  @synchronized_with(lock)
  def foo(self, x):
    return x*2

class instance_level_lock:
  lock = lambda self, *args, **kw : self._lock
  def __init__(self):
    self._lock = threading.RLock()

  @synchronized_with(lock)
  def foo(self, x):
    return x*2

Index

Feed

Other

Link

Pathtraq

loading...