read
and expect/expect_exact
do different things:
read
is best for forcing output, such as plots, but without a buffer size, it will read until it encounters and EOF, effectively closing the child implicitly (see pexpect.spawn.read).
expect
reads all output after a spawn
or the last send/sendline
, for an open child process. expect
will not usually close a child, unless it reaches a timeout
(see pexpect.spawn.exact).
Here's an example of what I mean:
NOTE - Tested on Ubuntu 20.04, using Python 3.8
import pexpect
# This child executes a single command and closes implicitly
cli = pexpect.spawn("ls -l")
# I use expect_exact when using symbols like $ (also used by expect's regex)
index = cli.expect_exact(["$", pexpect.EOF, ])
if index == 0:
print("First child still open, so use *before*:\n", cli.before)
cli.close()
else:
# This will happen
print("First child closed, so use *read*:\n", cli.read())
# The child stays open after this command. You should close this child explicitly
cli = pexpect.spawn("/bin/bash")
index = cli.expect_exact(["$", pexpect.EOF, ])
if index == 0:
# This will happen
cli.sendline("ls -l")
cli.expect_exact("$")
print("Next child still open, so use *before*:\n", cli.before)
cli.close()
else:
print("Next child closed, so use *read*:\n", cli.read())
Output:
First child closed, so use *read*:
b''
Next child still open, so use *before*:
b'ls -l\r\ntotal 28\r\n-rw-rw-r-- 1 ***** ***** 3393 Dec 1 15:52 *****.py\r\n-rw-rw-r-- 1 ***** ***** 1071 Dec 1 21:54 cli.py\r\n-rw-rw-r-- 1 ***** ***** 793 Nov 29 19:46 *****.py\r\n-rw-rw-r-- 1 ***** ***** 796 Nov 29 19:37 *****.py\r\n-rw-rw-r-- 1 ***** ***** 1118 Nov 29 16:05 *****.py\r\n-rw-rw-r-- 1 ***** ***** 709 Nov 29 16:21 *****.py\r\n-rw-rw-r-- 1 ***** ***** 376 Nov 22 19:47 *****.log\r\n
As you can see, read
can be hit or miss. For in-and-out CLI commands, I recommend pexpect.run
instead:
import pexpect
list_of_commands = ["ls -l", ]
for c in list_of_commands:
command_output, exitstatus = pexpect.run(c, withexitstatus=True)
if exitstatus != 0:
raise RuntimeError("Unable to {0}: {1}".format(c, command_output.strip()))
print(command_output.strip().decode())
Output:
total 28
-rw-rw-r-- 1 ***** ***** 3393 Dec 1 15:52 *****.py
-rw-rw-r-- 1 ***** ***** 1071 Dec 1 21:54 cli.py
-rw-rw-r-- 1 ***** ***** 793 Nov 29 19:46 *****.py
-rw-rw-r-- 1 ***** ***** 796 Nov 29 19:37 *****.py
-rw-rw-r-- 1 ***** ***** 1118 Nov 29 16:05 *****.py
-rw-rw-r-- 1 ***** ***** 709 Nov 29 16:21 *****.py
-rw-rw-r-- 1 ***** ***** 376 Nov 22 19:47 *****.log
Good luck with your code!