Unfortunately, it may not be as easy as reading from bot.stdout and writing to bot.stdin. Reason being, some programs do not flush to STDOUT until the program is done executing if it's a child process. The way to get around this is to spawn it under a pseudo-terminal. Here's an example using the pty module:
bot1.py
#!/usr/bin/env python
name = raw_input("What is your name?\n")
print "Hello {}, my name is Bot1".format(name)
raw_input() # Bot2: Hello Bot1
bot2.py
#!/usr/bin/env python
raw_input() # Bot1: What is your name?
print "Bot2"
greeting = raw_input() # Bot1: Hello Bot2, my name is Bot1
print "Hello {}".format(greeting.split()[-1])
run.py
#!/usr/bin/env python
import os
import pty
import termios
class Bot:
def __init__(self, name, program):
self.name = name
# Fork a process in a pseudo-terminal
self._pid, self._fd = pty.fork()
if self._pid == 0:
# Child process, replace with program
os.execvp(program, [program])
# Turn off echoing for child file descriptor, otherwise it will spew the
# child's output to the parent's STDOUT.
attribs = termios.tcgetattr(self._fd)
attribs[3] = attribs[3] & ~termios.ECHO
termios.tcsetattr(self._fd, termios.TCSANOW, attribs)
def speak(self, bot):
output = self.read()
bot.write(output)
print '{} -> {}: {}'.format(self.name, bot.name, output)
def read(self):
return os.read(self._fd, 1024).strip()
def write(self, line):
os.write(self._fd, line + "\n")
if __name__ == '__main__':
bot1 = Bot('Bot1', './bot1.py')
bot2 = Bot('Bot2', './bot2.py')
# Bot1 -> Bot2: What is your name?
bot1.speak(bot2)
# Bot2 -> Bot1: Bot2
bot2.speak(bot1)
# Bot1 -> Bot2: Hello Bot2, my name is Bot1
bot1.speak(bot2)
# Bot2 -> Bot1: Hello Bot1
bot2.speak(bot1)
output
$ ./run.py
Bot1 -> Bot2: What is your name?
Bot2 -> Bot1: Bot2
Bot1 -> Bot2: Hello Bot2, my name is Bot1
Bot2 -> Bot1: Hello Bot1
It's a simple example, but hopefully it's enough to get you started.