Programming Erlang style in Python :-)

Dominic oblivious at web.de
Sun Apr 6 16:46:39 EDT 2003


Python's dynamic capabilities allow it to
program finite state machines and asynchronous
message passing similar to the programming
language Erlang which is used in soft-realtime
telecommunication systems.

The first demonstration implements a finite state
machine in a recursive manner. By using
generators recursion is actually removed :)

The 2nd demonstration shows two objects which
send messages to each other asynchronously
Real argument pattern matching like in Erlang
has not been implemented though.

Enjoy :)

Ciao,
  Dominic

P.S. This 'pattern' could be used for keeping state
      in a server for example.

Output:

>>>>>>>>>>>>>>>>>>>>>>>>>
>>> Finite State Demo >>>
>>>>>>>>>>>>>>>>>>>>>>>>>
access denied to Schmitt
access denied to Mayer
2 failed attempts so far
access denied to Schmitt
access denied to Mayer
4 failed attempts so far
access denied to Schmitt
access denied to Mayer
6 failed attempts so far
access granted
connected Dominic, previous failed attempts 6

>>>>>>>>>>>>>>>>>>>>>>>>
>>>  Ping-Pong Demo  >>>
>>>>>>>>>>>>>>>>>>>>>>>>
ping got pong
pong got ping
ping got pong
pong got ping
ping got pong
pong got ping
ping got pong
pong got ping
ping got pong
pong got ping
ping got pong
pong got ping
ping got pong
pong got ping

Source:


from __future__ import generators
import sys

class Queue(list):
	
	
	def send(self,cmd, *args):
		self.insert(0,(cmd,args))
		self.items={}

	def __init__(self):
		self.items={}
		self.queue=self
		
	def __getattr__(self,name):
		return self.items[name]

	def receive(self,expect):
		"""Lot's of interesting stuff could be done here"""
		expect=expect.split(',')
		msg=self[-1]
		if msg[0]==expect[0]:
			args=list(msg[1])
			expect=expect[1:]
			for i in xrange(0,len(expect)):
				self.items[expect[i]]=args[i]
			self.pop()
			return 1
		else:
			return 0

############################################################

def ping(_q):
	if _q.receive('pong,pid'):
		print 'ping got pong'
		_q.pid.send('ping',_q)
		
	yield ping(_q)

def pong(_q):

	if _q.receive('ping,pid'):
		print 'pong got ping'
		_q.pid.send('pong',_q)
		
	yield pong(_q)

############################################################

def client(_q, _name, _password, _failed=0):
	
	if _q.receive('login,name,password'):
		if _q.name==_name and _q.password==_password:
			print 'access granted'
			yield connected(_q,_name,_failed)
		else:
			
			print 'access denied to %s' % _q.name
			if _failed>20:
				print 'too many bad login attempts'
				raise 'bad login'

			yield client(_q,_name,_password,_failed+1)
			
	elif _q.receive('info'):
		print '%d failed attempts so far' % _failed
		yield client(_q,_name,_password,_failed)
	else:
		_q.pop()

def connected(_q,_name,_failed):

	if _q.receive('info'):
		print 'connected %s, previous failed attempts %d' % (_name,_failed)

	yield connected(_q,_name,_failed)
	
############################################################

print '>>>>>>>>>>>>>>>>>>>>>>>>>'
print '>>> Finite State Demo >>>'
print '>>>>>>>>>>>>>>>>>>>>>>>>>'

sys.stdin.readline()

queue=Queue()
c=client(queue,'Dominic','1234',_failed=0)

for x in xrange(1,4):
	
	queue.send('login','Schmitt','798')
	queue.send('login','Mayer','123')
	queue.send('info')

	# Scheduler
	while 1:
		c=c.next()
		if len(queue)==0:
			break

queue.send('login','Dominic','1234')
c=c.next()

queue.send('info')
c=c.next()




print '\n>>>>>>>>>>>>>>>>>>>>>>>>'
print '>>>  Ping-Pong Demo  >>>'
print '>>>>>>>>>>>>>>>>>>>>>>>>'

sys.stdin.readline()


# Two "tasks" which exchange messages

queue_pong=Queue()
queue_ping=Queue()

# initiate
queue_ping.send('pong',queue_pong)

pg=pong(queue_pong)
pi=ping(queue_ping)

# 'Scheduler'
for tmp in xrange(1,8):
   pi=pi.next()
   pg=pg.next()









More information about the Python-list mailing list