2011-03-16 7 views
1

다양한 잠금을 사용하는 다중 스레드 Python 응용 프로그램을 디버깅하려고합니다. 모든 장소와 잠금 획득 및 출시 추적 할 수있는 샷을 통해 문, 내 생각이 방법 을 장식하는 threading.Lock.acquire 오히려 장소 log.debug (...)보다로깅 잠금 다중 스레드 응용 프로그램에서 호출 획득 및 해제

()threading.Lock.release(), 다음과 같이 자신의 호출을 앞에 :

로그 일부 글로벌 로깅 개체입니다
log.debug("lock::acquire() [%s.%s.%s]" % 
      (currentThread().getName(), 
      self.__class__.__name__, 
      sys._getframe().f_code.co_name)) 

- 토론을 위해서입니다. 에 관계없이 어느 이러한 방법은 출력의 이름, 작업이 장식하는 로그에 호출되는 객체를 잠글 수 있도록

지금 이상적으로 이름 가 런타임에 파생되어야하는 로그 항목에 "잠금"현재 스레드, 클래스 및 작업 (acquire | release)이 호출되는 함수입니다.

면책 조항 : 위의 코드는 이러한 장식 구현에 충분하지 않음을 인정합니다. 그것은 내가 성취 할 수 있다고 생각되는 것의 맛을 내기 위해서만 제공됩니다.

라이브러리 (예 : 호출 응용 프로그램 코드)를 원본 소스 코드로 처리하지 않고 표준 라이브러리 메소드를 꾸밀 수있는 사람은 누구입니까?

아마도 내가 틀린 나무를 짖고 있는데 장식자를 사용하지 않고 같은 목적을 달성하는 더 좋은 방법이 있을까요? 이것이 사실이라면 사전에 많은 안내에 감사드립니다.

해결 방법 : (lazyr에서 영감) 다음 코드는 잠금 작업을 기록하고 나에게 잠금 작업을 호출하는 방법/함수의 이름을 제공

는 (나는 또한 조건에서 작동하도록 코드를 채택하고과 추가 대기()는() 방법) 통보 : 로그 인스턴스가 LogLock에 전달

# Class to wrap Lock and simplify logging of lock usage 
class LogLock(object): 
    """ 
    Wraps a standard Lock, so that attempts to use the 
    lock according to its API are logged for debugging purposes 

    """ 
    def __init__(self, name, log): 
     self.name = str(name) 
     self.log = log 
     self.lock = threading.Lock() 
     self.log.debug("{0} created {1}".format(
      inspect.stack()[1][3], self.name)) 

    def acquire(self, blocking=True): 
     self.log.debug("{0} trying to acquire {1}".format(
      inspect.stack()[1][3], self.name)) 
     ret = self.lock.acquire(blocking) 
     if ret == True: 
      self.log.debug("{0} acquired {1}".format(
       inspect.stack()[1][3], self.name)) 
     else: 
      self.log.debug("{0} non-blocking acquire of {1} lock failed".format(
       inspect.stack()[1][3], self.name)) 
     return ret 

    def release(self): 
     self.log.debug("{0} releasing {1}".format(inspect.stack()[1][3], self.name)) 
     self.lock.release() 

    def __enter__(self): 
     self.acquire() 

    def __exit__(self, exc_type, exc_val, exc_tb): 
     self.release() 
     return False # Do not swallow exceptions 

.

# With the following format 
log_format = \ 
     logging.Formatter('%(asctime)s %(levelname)s %(threadName)s %(message)s') 
+0

모니터링하려는 코드가 사용자가 제어 할 수 있다면 Lock의 자손을 만들고 코드에서 사용하는 것이 더 쉬울 것입니다[email protected]는'__init__' 생성자에서 인스턴스별로 적용될 때 더 쉽습니다. – Apalala

답변

3

나는 최근에 당신의 문제가 있었다 : 초기화이 주어 나에게 호출 스레드의 ID를 다음과 같이가 logging.Formatter로 정의 하였다. 내 로거가 자동으로 스레드 이름을 기록하도록 설정했습니다. this 답변과 같습니다. 나는 잠금을 서브 클래 싱 할 수 없었습니다 발견, 그래서 다음과 같이 그것을 포장했다 : 나는 같은 이름을 가진 여러 개의 잠금 장치를 구분할 수 있도록 내가 개체의 ID를 기록

class LogLock(object): def __init__(self, name): self.name = str(name) self.lock = Lock() def acquire(self, blocking=True): log.debug("{0:x} Trying to acquire {1} lock".format( id(self), self.name)) ret = self.lock.acquire(blocking) if ret == True: log.debug("{0:x} Acquired {1} lock".format( id(self), self.name)) else: log.debug("{0:x} Non-blocking aquire of {1} lock failed".format( id(self), self.name)) return ret def release(self): log.debug("{0:x} Releasing {1} lock".format(id(self), self.name)) self.lock.release() def __enter__(self): self.acquire() def __exit__(self, exc_type, exc_val, exc_tb): self.release() return False # Do not swallow exceptions 

, 당신은 그렇지 않을 수 있습니다 필요해.

관련 문제