Python fdpexpect with multiple expects

Viewed 104

Testing the simple example that should execute the external application and catch both inputs there.

# external_application.py
print('First_line:')
x = input()

print('Second_line:')
y = input()

print(f'Done: {x} and {y}')

And the runner:

# runner.py
import subprocess
import pexpect.fdpexpect

p = subprocess.Popen(("python", "external_application.py"), stdin=subprocess.PIPE, stdout=subprocess.PIPE)

session = pexpect.fdpexpect.fdspawn(p.stdout.fileno())

session.expect("First_line:")
p.stdin.write(b'1')
print('first_done')

session.expect("Second_line:")
p.stdin.write(b'2')
print('second_done')

p.stdin.close()
print(f'Result: {p.stdout.read()}')

I can see that output of the print('first_done') and then it locks on the second expect. If we remove the second input and a second expect then everything works correctly till the end.
Running on the windows, python 3.7.9, pexpect 4.8.0
Am I missing some timeout or a flush?

1 Answers

When I check the dump, session matches b'First_line:\r\n', but p.stdin.write doesn't move the pexpect cursor forward to look for "Second_line:", as what happens with send() or sendline().

May I suggest a simpler way, using PopenSpawn? The docs state that it "provides an interface like pexpect.spawn interface (sic) using subprocess.Popen":

NOTE - Tested in Windows 11, using Python 3.9.

import pexpect
from pexpect import popen_spawn

session = pexpect.popen_spawn.PopenSpawn("python external_application.py")
session.expect("First_line:")
session.sendline("1")
print("first_done")

session.expect("Second_line:")
session.sendline("2")
print("second_done")

print(session.read().decode("utf-8"))

Output:

first_done
second_done

Done: 1 and 2
Related