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