36
child = pexpect.spawn ('/bin/bash')
child.sendline('ls')
print(child.readline())
print child.before, child.after

All I get with this code in my output is

ls

ls 

But when my code is

child = pexpect.spawn('ls')
print(child.readline())
print child.before, child.after

Then it works, but only for the first 2 prints. Am I using the wrong send command? I tried send, write, sendline, and couldn't find anymore.

user2579116
  • 473
  • 1
  • 4
  • 8

8 Answers8

26

In pexpect the before and after attributes are populated after an expect method. The most common thing used in this situation is waiting for the prompt (so you'll know that the previous command finished execution). So, in your case, the code might look something like this:

child = pexpect.spawn ('/bin/bash')
child.expect("Your bash prompt here")
child.sendline('ls')
#If you are using pxssh you can use this
#child.prompt()
child.expect("Your bash prompt here")
print(child.before)
devforfu
  • 1,570
  • 1
  • 19
  • 41
Catalin Luta
  • 711
  • 4
  • 8
  • 2
    Is there a way to ignore the command that you wrote when you print `child.before`? I suppose I just trim until I see the `\r\n`. – CMCDragonkai Apr 17 '20 at 09:18
20

Try the following:

import pexpect
child = pexpect.spawn('ls')
print child.read() # not readline

The read() will give you the entire output of the ls.

josliber
  • 43,891
  • 12
  • 98
  • 133
mvensky
  • 209
  • 2
  • 2
  • also works for `spawnu` in my testing, where the other top answers did not. Might need to first verify the command has finished, although probably won't matter for `ls`. – AlanSE Mar 29 '17 at 19:09
15
#!/usr/bin/env python

import pexpect
child = pexpect.spawn("ssh root@172.16.0.120c -p 2222")
child.logfile = open("/tmp/mylog", "w")
child.expect(".*assword:")
child.send("XXXXXXX\r")
child.expect(".*\$ ")
child.sendline("ls\r")
child.expect(".*\$ ")

go to open your logfile:- go to terminal

$gedit /tmp/mylog

As Per https://pexpect.readthedocs.io/en/stable/api/pexpect.html#spawn-class

# In Python 3, we'll use the ``encoding`` argument to decode data
# from the subprocess and handle it as unicode:
 child = pexpect.spawn('some_command', encoding='utf-8')
 child.logfile = sys.stdout
Reegan Miranda
  • 2,879
  • 6
  • 43
  • 55
7

I think all you need is:

p = pexpect.spawn('ls')
p.expect(pexpect.EOF)
print(p.before)

or

p = pexpect.spawn('/bin/ls')
p.expect(pexpect.EOF)
print(p.before)

or

p = pexpect.spawn('/bin/bash -c "ls"')
p.expect(pexpect.EOF)
print(p.before)

or even

print(pexpect.run('ls'))
Stanislav
  • 826
  • 11
  • 17
3
import sys
import pexpect
child = pexpect.spawn('ls')
child.logfile = sys.stdout
child.expect(pexpect.EOF)

See the manual entry on the subject.

djhaskin987
  • 9,741
  • 4
  • 50
  • 86
  • 2
    Caveat: if `child.sendline(...)` is the last line of the program, the output won't (have the time to) be captured. Expecting an EOF helps: `child.expect(pexpect.EOF)`. http://pexpect.readthedocs.io/en/stable/commonissues.html#truncated-output-just-before-child-exits – Victor Sergienko May 22 '17 at 18:50
  • @VictorSergienko Edited. Thanks! – djhaskin987 May 25 '17 at 18:50
  • 1
    Couple more notes: 1. I'd assign `logfile` first. 2. Expecting EOF only works if the stream actually ends. If we're spawning a shell, we have to explicitly add `exit` as a last command. – Victor Sergienko May 25 '17 at 19:07
  • Wasn't spawning a shell here, but that is a good point. Added the other thing, though. – djhaskin987 May 26 '17 at 19:20
1

copy from class spawn(SpawnBase) docstring, maybe example-2 is what you want.

Example log input and output to a file::

child = pexpect.spawn('some_command')
fout = open('mylog.txt','wb')
child.logfile = fout

Example log to stdout::

# In Python 2:
child = pexpect.spawn('some_command')
child.logfile = sys.stdout

# In Python 3, we'll use the ``encoding`` argument to decode data
# from the subprocess and handle it as unicode:
child = pexpect.spawn('some_command', encoding='utf-8')
child.logfile = sys.stdout
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
yongxu
  • 21
  • 5
0

You can use a simple package tiotrap, which contains TextIOTrap helper class for managing TextIO Streams.

Installation:

python3 -m pip install tiotrap

For example:

tio_trap = tiotrap.TextIOTrap(store=True)
p = pexpect.spawn('ls -la')
p.logfile = tio_trap
p.expect(pexpect.EOF)
print(f"ls output:\n{str(tio_trap)}\n~")
Timothy C. Quinn
  • 3,739
  • 1
  • 35
  • 47
0

for me the logfile approach wasn't working as it contained a bunch of escape characters I couldn't get rid off.

I ended up echoing the cmd-output, e.g. if your OS is ubuntu:

child.sendline(yourcommand > logfile.txt)