Vader Vader - 3 months ago 19
Python Question

Interaction with Python cmd module

I have a program that uses

cmd
module and looks like this:

import cmd


class Prog(cmd.Cmd):

prompt = '>>'

def do_reverse(self, line):
print line[::-1]

def do_exit(self, line):
return True

if __name__ == '__main__':
Prog().cmdloop()


I want to write to programs
stdin
and read from its
stdout
programmatically. I'm trying to achieve that as follows:

from subprocess import Popen, PIPE


class ShellDriver(object):
def __init__(self, process):
self.process = process
self.prompt = '>>'
self.output = ''
self.read()

def read(self):
while not self.output.endswith(self.prompt):
chars = self.process.stdout.read(1)
if chars == '':
break
self.output += chars

result = self.output.replace('\n' + self.prompt, '')
self.output = ''
return result

def execute(self, command):
self.process.stdin.write(command + '\n')
return self.read()

if __name__ == '__main__':
p = Popen(['python', 'prog.py'], stdin=PIPE, stdout=PIPE)
cmd = ShellDriver(p)
print cmd.execute('reverse abc')
cmd.execute('exit')


However when I ran this code from PyCharm it works fine, but when I ran it from command line it hangs. As I understood there is a conflict between consoles (console that reader script is running from and programs console) since they are trying to use the same pipes, and this issue doesn't exist in PyCharm because it redirects I\O to its own console.

Is there a way to get this working in the system console?

I'm on Windows (cross platform solution is preferable) and Python 2.7

Answer

Finally found an answer. By default interpreter works in buffered mode sending data to stdout in chunks, in order to avoid that it should be running in unbuffered mode with -u command line argument:

p = Popen(['python', '-u', 'prog.py'], stdin=PIPE, stdout=PIPE)
Comments