== A simple Python class to trace access to object attributes Every now and then I run into a situation where I want to know what attributes on an object are getting accessed when. Fortunately it's pretty easy to knock together something to do this, in a variant on the [[mutating proxy pattern MutatingProxies]]. Here is a sample implementation, as a ((Tracer)) class: def _repon(obj, n): return (not obj._t_il) or \ (n in obj._t_il) class Tracer(object): def __init__(self, real, name = None, monitor = None): self._t_ro = real if name: self._t_nm = name else: cl = real.__class__ self._t_nm = "<%s.%s>" % \ (cl.__module__, cl.__name__) self._t_il = monitor def __getattr__(self, n): if _repon(self, n): print "get %s.%s" % (self._t_nm, n) return getattr(self._t_ro, n) def __setattr__(self, n, v): if n in ("_t_nm", "_t_ro", "_t_il"): super(Tracer, self).__setattr__(n, v) return if _repon(self, n): print "set %s.%s" % (self._t_nm, n) setattr(self._t_ro, n, v) def __delattr__(self, n): if _repon(self, n): print "del %s.%s" % (self._t_nm, n) delattr(self._t_ro, n) You use it by replacing the original object with _Tracer(obj)_. The optional _name_ argument will be used as the object's name in output; the optional _monitor_ argument is a list of attributes to monitor access to (if omitted, all attributes are monitored). There's a couple of limitations in this approach: * 'get' is printed when you do _hasattr()_, because _hasattr()_ works by getting the attribute and seeing if that throws an error. * you can't tell a method call from an attribute access, because Python [[doesn't really distinguish them AttributeAccessorAnnoyance]]. As a side note, the ((_repon)) function is not a class function in order to keep it out of the object namespace. I could keep the three variables out too if I wanted to work hard enough, by using a closure, but that would complicate and obscure the code. (Disclaimer: the indentation has been shrunk and the variable names shortened in the interests of not overflowing WanderingThoughts' margins. I do not write real code that is this condensed.)