我想調試使用各種鎖的多線程Python應用程序。記錄鎖獲取和釋放多線程應用程序中的調用
而不是地方log.debug(...)語句各地拍來跟蹤何時何地鎖獲取和釋放,我的想法是裝飾方法threading.Lock.acquire()和threading.Lock.release(),並且用類似下面的前綴它們的調用:
log.debug("lock::acquire() [%s.%s.%s]" %
(currentThread().getName(),
self.__class__.__name__,
sys._getframe().f_code.co_name))
凡日誌是一些全球記錄對象 - 爲討論的緣故。
現在最好的名字在日誌條目中「鎖定」將會在運行時得到,因此不管是哪個的鎖定對象,這些方法是基於日誌調用將輸出它的名字,裝飾操作,當前線程,類,以及調用操作(獲取|釋放)的功能。
免責聲明:我承認上面給出的代碼對於任何這樣的裝飾器實現都是不夠的。只是提供我認爲可以實現的東西的味道。
有沒有人知道我是否可以裝飾標準庫方法,而不必修改線程庫的原始源代碼,即從我的調用應用程序代碼中?
也許我在吠叫錯誤的樹,並且有更好的方法來實現相同的目的,而不使用裝飾器?如果確實如此,非常感謝任何指導。
解決方案:(由lazyr啓發)
下面的代碼記錄鎖定操作和給我的方法/函數調用鎖定操作的名稱(我也適應代碼條件下正常工作及其附加的wait()和通知()方法):
# 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
凡日誌實例傳遞給LogLock。
# With the following format
log_format = \
logging.Formatter('%(asctime)s %(levelname)s %(threadName)s %(message)s')
如果您要監視的代碼在您的控制之下,那麼創建Lock的後代並讓您的代碼使用它會更容易。即使@decorators在'__init__'構造函數的每個實例上應用時也更容易。 – Apalala 2011-03-16 15:44:50