As @Ron Reiter pointed out, you can’t use readline()
because cout
doesn’t print newlines implicitly — you either need std::endl
or "\n"
here.
For an interactive use, when you can’t change the child program, pexpect
module provides several convenience methods (and in general it solves for free: input/output directly from/to terminal (outside of stdin/stdout) and block-buffering issues):
#!/usr/bin/env python
import sys
if sys.version_info[:1] < (3,):
from pexpect import spawn, EOF # $ pip install pexpect
else:
from pexpect import spawnu as spawn, EOF # Python 3
child = spawn("./randomNumber") # run command
child.delaybeforesend = 0
child.logfile_read = sys.stdout # print child output to stdout for debugging
child.expect("enter a number: ") # read the first prompt
lo, hi = 0, 100
while lo <= hi:
mid = (lo + hi) // 2
child.sendline(str(mid)) # send number
index = child.expect([": ", EOF]) # read prompt
if index == 0: # got prompt
prompt = child.before
if "too high" in prompt:
hi = mid - 1 # guess > num
elif "too low" in prompt:
lo = mid + 1 # guess < num
elif index == 1: # EOF
assert "Congratulations" in child.before
child.close()
break
else:
print('not found')
child.terminate()
sys.exit(-child.signalstatus if child.signalstatus else child.exitstatus)
It works but it is a binary search therefore (traditionally) there could be bugs.
Here’s a similar code that uses subprocess
module for comparison:
#!/usr/bin/env python
from __future__ import print_function
import sys
from subprocess import Popen, PIPE
p = Popen("./randomNumber", stdin=PIPE, stdout=PIPE,
bufsize=1, # line-buffering
universal_newlines=True) # enable text mode
p.stdout.readline() # discard welcome message: "This program gener...
readchar = lambda: p.stdout.read(1)
def read_until(char):
buf = []
for c in iter(readchar, char):
if not c: # EOF
break
buf.append(c)
else: # no EOF
buf.append(char)
return ''.join(buf).strip()
prompt = read_until(':') # read 1st prompt
lo, hi = 0, 100
while lo <= hi:
mid = (lo + hi) // 2
print(prompt, mid)
print(mid, file=p.stdin) # send number
prompt = read_until(':') # read prompt
if "Congratulations" in prompt:
print(prompt)
print(mid)
break # found
elif "too high" in prompt:
hi = mid - 1 # guess > num
elif "too low" in prompt:
lo = mid + 1 # guess < num
else:
print('not found')
p.kill()
for pipe in [p.stdin, p.stdout]:
try:
pipe.close()
except OSError:
pass
sys.exit(p.wait())