Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在多线程应用程序中记录锁获取和释放调用_Python_Multithreading_Debugging_Decorator_Locks - Fatal编程技术网

Python 在多线程应用程序中记录锁获取和释放调用

Python 在多线程应用程序中记录锁获取和释放调用,python,multithreading,debugging,decorator,locks,Python,Multithreading,Debugging,Decorator,Locks,我正在尝试调试一个使用各种锁的多线程Python应用程序 我的想法不是在整个快照中放置log.debug(…)语句来跟踪锁的获取和释放时间和地点,而是对threading.Lock.acquire()和threading.Lock.release()方法进行修饰,并在调用之前加上如下前缀: log.debug("lock::acquire() [%s.%s.%s]" % (currentThread().getName(), self.__class__

我正在尝试调试一个使用各种锁的多线程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))
其中,log是一些全局的日志记录对象-为了便于讨论

现在理想情况下,应该在运行时派生日志项中的名称“lock”,这样无论在日志上调用哪个lock对象,这些方法都将输出其名称、修饰的操作、调用操作(获取|释放)的当前线程、类和函数

免责声明:我承认上述代码不足以实现任何此类装饰器。这只是为了给我一个我认为可以实现的体验

有人知道我是否可以修饰标准库方法,而无需修改线程库的原始源代码,即从调用应用程序代码中修改

也许我找错了方向,有更好的方法来达到同样的目的,而不使用装饰师?如果情况确实如此,请提前感谢您的指导

解决方案:(受懒人启发)

下面的代码记录了锁定操作,并给出了调用锁定操作的方法/函数的名称(我也在调整代码,使其能够处理条件及其附加的wait()notify()方法):

其中,日志实例传递给LogLock。init是使用logging.Formatter定义的,如下所示,以提供调用线程的标识:

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

我最近遇到了你的问题。我将日志记录器设置为自动记录线程名称,如答案中所示。我发现不可能将Lock子类化,所以我必须将其包装,如下所示:

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

我记录了对象的id,以便区分多个具有相同名称的锁,您可能不需要它。

如果要监视的代码在您的控制下,则创建锁的后代并让您的代码使用它会更容易。在
\uuuu init\uuuuu
构造函数上基于每个实例应用@decorator时,即使是@decorator也更容易。
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