Можно ли создать подклассы объектов Lock () в Python?Если нет, другие способы отладки тупика? - PullRequest
7 голосов
/ 21 июля 2011

Итак, у меня есть многопоточная программа на Python, которая в настоящее время страдает от тупиковой ситуации. Я собирался зарегистрировать получение блокировки путем создания подклассов threading.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. Можно ли подкласс блокировать объекты, чтобы делать то, что я делаю?

  2. Если нет, то как лучше всего отлаживать тупик в python?

Примечание: я не пишу никаких расширений Python. Есть похожий вопрос: Как отлаживать тупик с питоном? Тем не менее, он имеет дело с компиляцией кода C ++ и использованием GDB, чего я не могу сделать, так как мой код - чистый python.

Ответы [ 3 ]

15 голосов
/ 21 июля 2011

Вы можете просто использовать подход «имеет блокировку» по сравнению с подходом «является блокировкой», например:

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()

, где я включил соответствующие средства защиты контекста, так как вы, вероятно, хотите использоватьwith синтаксис с вашими замками (кто бы не стал?).

Использование показано ниже:

    >>> lock = DebugLock()
    >>> with lock:
    ...     print "I'm atomic!"
    ... 
    acquired <__main__.DebugLock object at 0x7f8590e50190>
    I'm atomic!
    released <__main__.DebugLock object at 0x7f8590e50190>
    >>>
4 голосов
/ 21 июля 2011

Расс ответил на важный вопрос (# 2), я отвечу на вопрос # 1.

Не представляется возможным.threading.Lock () - заводская функция ( документация ).Он вызывает thread.allocate_lock () - нет контроля над созданием объекта Lock.Вы также не можете monkeypatch определение класса 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'
2 голосов
/ 21 июля 2011

Если вы хотите сделать что-то вроде наследования, не сталкиваясь с этой ошибкой, я предлагаю вам попробовать

 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()

, и он завис, поэтому я думаю, что он работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...