2011-07-21 6 views
6

私は現在、デッドロックに苦しんでいるマルチスレッドのPythonプログラムを持っています。私はthreading.Lockオブジェクトをサブクラス化することで取得したロックをログに記録するつもりだった:私はプログラムを実行しようとするとPythonでLock()オブジェクトをサブクラス化することは可能ですか?そうでない場合、デッドロックをデバッグする他の方法はありますか?

import traceback 
class DebugLock(threading.Lock): 
    def acquire(self): 
     print >>sys.stderr, "acquired", self 
     #traceback.print_tb 
     threading.Lock.acquire(self) 
    def release(self): 
     print >>sys.stderr, "released", self 
     #traceback.print_tb 
     threading.Lock.release(self) 

は、私は次のエラーを取得する:

class DebugLock(threading.Lock): 
TypeError: Error when calling the metaclass bases 
    cannot create 'builtin_function_or_method' instances 

だから、私の質問は二つある:

  1. Lockオブジェクトをサブクラス化して、自分のやることはできますか?

  2. もしそうでなければ、デッドロックをPythonでデバッグする最良の方法は何ですか?

注:私はPython拡張機能を書いていません。同様の質問があります:How to debug deadlock with python? しかし、C++コードのコンパイルとGDBの使用について扱っています。私のコードは純粋なPythonであるため、できません。

答えて

13

あなたはそうのように、アプローチ「ロックです」対「ロックを持っている」使用することができます

あなたはおそらく withを使用したいので、私は適切なコンテキストガードで投げてきた
import threading, traceback, sys 
class DebugLock(object): 
    def __init__(self): 
     self._lock = threading.Lock() 
    def acquire(self): 
     print >>sys.stderr, "acquired", self 
     #traceback.print_tb 
     self._lock.acquire() 
    def release(self): 
     print >>sys.stderr, "released", self 
     #traceback.print_tb 
     self._lock.release() 
    def __enter__(self): 
     self.acquire() 
    def __exit__(self, type, value, traceback): 
     self.release() 

あなたのロックを使った構文(誰がそうしないだろう?)。以下に示す

使用法:ラスは、重要な質問(#2)の答え

 
    >>> lock = DebugLock() 
    >>> with lock: 
    ...  print "I'm atomic!" 
    ... 
    acquired <__main__.DebugLock object at 0x7f8590e50190> 
    I'm atomic! 
    released <__main__.DebugLock object at 0x7f8590e50190> 
    >>> 
+0

ありがとうございました。 – jmite

4

、私は質問の#1にお答えします。

可能性はありません。 threading.Lock()はファクトリ関数(documentation)です。これはthread.allocate_lock()を呼び出します。ロックオブジェクトの作成を制御することはできません。また、thread.LockTypeクラス定義(thread.piで公開されているクラススケルトン)をmonkeypatchできません。

>>> thread.LockType.foo = "blah" 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: can't set attributes of built-in/extension type 'thread.lock' 
2

あなたは、このエラーに実行せずに、継承のような何かをしたい場合は、私はあなたがself.__dict__.update(lock.__dict__)を使用して私の通常の方法が動作していないようです

import traceback 
from threading import Lock 
class DebugLock(): 
    def __init__(self,lock = None): 
     self.lock = lock or Lock() 

     # normally done with __dict__ 
     for command in dir(self.lock): 
      self.__dict__[command] = getattr(self.lock,command) 

を試してみてください示唆しています。私はこれをロックコードでテストしました

X = DebugLock() 
y = X.lock 
Y = DebugLock(y) 
X.acquire() 
Y.acquire() 
X.release() 
Y.release() 

それが動作していると思います。

関連する問題