Is it possible to subclass Lock() objects in Python? If not, other ways to debug deadlock?

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

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'

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.