是否可以在 Python 中子类化 Lock() 对象?如果没有,还有其他方法来调试死锁吗?

发布于 2024-11-25 14:58:40 字数 948 浏览 0 评论 0原文

所以,我有一个多线程Python程序,它目前正遭受死锁。我打算通过子类化线程来记录锁定获取。锁定对象:

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. 是否可以子类化锁定对象来执行我的操作我在做什么?

  2. 如果没有,调试 python 死锁的最佳方法是什么?

注意:我没有编写任何 Python 扩展。还有一个类似的问题:How to debug deadlock with python? 然而,它涉及编译 C++ 代码和使用 GDB,这是我无法做到的,因为我的代码是纯 python。

So, I've got a multithreaded python program, which is currently suffering from deadlock. I was going to log lock acquiring by subclassing threading.Lock objects:

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)  

When I try to run the program, I get the following error:

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

So, my question is twofold:

  1. Is it possible to subclass Lock objects to do what I'm doing?

  2. If not, what is the best way to debug deadlock in python?

Note: I'm not writing any Python extension. There's a similar question: How to debug deadlock with python?
However, it deals with compiling C++ code and using GDB, which I can't do since my code is pure python.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一刻暧昧 2024-12-02 14:58:41

您可以只使用“有锁”与“是锁”方法,如下所示:

import threading, traceback, sys
class DebugLock(object):
    def __init__(self):
        self._lock = threading.Lock()
    def acquire(self):
        print("acquired", self)
        #traceback.print_tb
        self._lock.acquire()
    def release(self):
        print("released", self)
        #traceback.print_tb
        self._lock.release()
    def __enter__(self):
        self.acquire()
    def __exit__(self, type, value, traceback):
        self.release()

我在其中添加了适当的上下文保护,因为您可能希望对锁使用 with 语法(谁不会?)。

用法如下图所示:

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

You could just use the "has a lock" versus "is a lock" approach, like so:

import threading, traceback, sys
class DebugLock(object):
    def __init__(self):
        self._lock = threading.Lock()
    def acquire(self):
        print("acquired", self)
        #traceback.print_tb
        self._lock.acquire()
    def release(self):
        print("released", self)
        #traceback.print_tb
        self._lock.release()
    def __enter__(self):
        self.acquire()
    def __exit__(self, type, value, traceback):
        self.release()

where I've thrown in the appropriate context guards since you likely want to use the with syntax with your locks (who wouldn't?).

Usage shown below:

    >>> lock = DebugLock()
    >>> with lock:
    ...     print("I'm atomic!")
    ... 
    acquired <__main__.DebugLock object at 0x7f8590e50190>
    I'm atomic!
    released <__main__.DebugLock object at 0x7f8590e50190>
    >>>
热情消退 2024-12-02 14:58:41

Russ 回答了重要问题(#2),我将回答问题#1。

看来不可能。 threading.Lock() 是一个工厂函数(文档)。它调用 thread.allocate_lock() - 无法控制 Lock 对象的创建。您也无法对 thread.LockType 类定义(在 thread.pi 中公开的类骨架)进行猴子修补。

>>> 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'

Russ answered the important question (#2), I'll answer question #1.

Doesn't appear to be possible. threading.Lock() is a factory function (documentation). It calls thread.allocate_lock() - there's no control over Lock object creation. You also cannot monkeypatch the thread.LockType class definition (the class skeleton exposed in thread.pi).

>>> 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'
吃兔兔 2024-12-02 14:58:41

如果您想做继承之类的事情而不遇到此错误,我建议您尝试

 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)

使用 self.__dict__.update(lock.__dict__) 的正常方法似乎不起作用。我用锁定代码测试了它

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

并且挂起,所以我认为它是有效的。

If you want to do something like inheritance without running into this error, I suggest you try

 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)

My normal method of using self.__dict__.update(lock.__dict__) doesn't seem to be working. I tested this out with the locking code

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

and that hangs, so I think it is working.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文