Programatically getting the calling object in Python

I have a dispatcher that I use to send messages from one object to another. If Object A wants to send a message to Object B, he uses the Dispatcher to send the message for him. Object A doesn’t care how the Dispatcher sends the message – it might need to be queued and sent across threads for example.

When Object B receives the message, he might want to know who sent the message so that he can reply to him. In order to do this, when Object A tells the Dispatcher to send a message he also tells him who the messages is coming from.

Here is a simple example. Note: I create the A1, B1, and Dispatcher1 objects on-the-fly to simplify the example. Hopefully that is not too distracting.



import inspect

class Dispatcher1:
	def send( self, srcObj, dstObj, *args, **kwargs ):
		print 'D1.send', 'srcObj =', str(srcObj), 'dstObj = ', str(dstObj)
		dstObj.recv( srcObj, args, kwargs )

class A1:
	def run( self ):
		print 'A1.run'
		Dispatcher1().send( self, B1() )

	def callback( self ):
		print 'A1.callback'

class B1:
	def recv( self, srcObj, *args, **kwargs ):
		print 'B1.recv'
		srcObj.callback()

if __name__ == '__main__':
	A1().run()
	print


Running the code gives this:



A1.run
D1.send srcObj = <__main__.A1 instance at 0x00B1AA58> dstObj =  <__main__.B1 instance at 0x00A9E378>
B1.recv
A1.callback


This is pretty standard stuff, but in a powerful language like Python, it seems to be a waste to make Object A have to say ‘Hey, I’m the one sending this message.’ What I would like to do is have the Dispatcher figure that out himself and automatically specify Object A as the sender.

I can do this by inspecting the stack each time send is called. Here is a modified example.



import inspect

class Dispatcher2:
	def send( self, dstObj, *args, **kwargs ):
		srcObj = inspect.stack()[1][0].f_locals['self']
		print 'Found srcObj =', str(srcObj)
		print 'D2.send', 'srcObj =', str(srcObj), 'dstObj = ', str(dstObj)
		dstObj.recv( srcObj, args, kwargs )

class A2:
	def run( self ):
		print 'A2.run'
		Dispatcher2().send( B2() )

	def callback( self ):
		print 'A2.callback'

class B2:
	def recv( self, srcObj, *args, **kwargs ):
		print 'B2.recv'
		srcObj.callback()

if __name__ == '__main__':
	A2().run()
	print


Running the code gives this:



A2.run
Found srcObj = <__main__.A2 instance at 0x00B1AA58>
D2.send srcObj = <__main__.A2 instance at 0x00B1AA58> dstObj =  <__main__.B2 instance at 0x00A9E210>
B2.recv
A2.callback


This seems like a lot of work to get the caller from the stack not to mention the appropriate error-handling is missing.

Another alternative is to add a send() function to Object A and then use a decorator to add the ‘self’ parameter before calling the Dispatcher’s send() function. But I would rather not require a send() function in Object A. There are a lot of different objects that will be using the Dispatcher. I don’t want them to have to add functions to each of them.

Does anyone have any other suggestions on how to accomplish this?

[Emphasis added.] IANA Python expert, but the bolded part immediately screams “inheritance” to me. You shouldn’t have to explicitly create multiple send functions; they should all inherit from a base class. Create a Dispatcher class with a send() function, then derive all of your dispatchers from it:


class Dispatcher(object):
  def send(self,dst):
    print "SENT  ",self,"to",dst
    dst.recv(self)

class Receiver(object):
  def recv(self,src):
    print "  RECV",src,"at",self

class A(Dispatcher): pass
class B(Dispatcher): pass

class Z(Receiver): pass
class Y(Receiver): pass

a = A()
b = B()
y = Y()
z = Z()

a.send(z)
b.send(z)
a.send(y)

which prints


SEND   <__main__.A object at 0x7ff2082c> to <__main__.Z object at 0x7ff2088c>
  RECV <__main__.A object at 0x7ff2082c> at <__main__.Z object at 0x7ff2088c>
SEND   <__main__.B object at 0x7ff2084c> to <__main__.Z object at 0x7ff2088c>
  RECV <__main__.B object at 0x7ff2084c> at <__main__.Z object at 0x7ff2088c>
SEND   <__main__.A object at 0x7ff2082c> to <__main__.Y object at 0x7ff2086c>
  RECV <__main__.A object at 0x7ff2082c> at <__main__.Y object at 0x7ff2086c>

Thanks Omphaloskeptic. I used inheritance for my first implementation, but I’d like to avoid it now. I’d like the objects that send messages to have the least amount of coupling with my Dispatcher as possible. If I use inheritance, then I’d have to tell users of my Dispatcher, “If you want to send messages with my Dispatcher, then your senders must inherit from this base class.”