Nathaniel M. Beaver
Nathaniel M. Beaver

Reputation: 755

Pexpect eats bash prompt

This expect script launches a bash shell that includes the prompt:

#! /usr/bin/env expect

spawn -noecho "bash"

expect "$ "

send "echo 'Hello, "

interact

e.g. user@host:/path/to/working/directory$ echo 'Hello,

I tried doing the same thing with Pexpect:

#! /usr/bin/env python

import pexpect

child = pexpect.spawn('bash')

index = child.expect("\$ ")

child.send("echo 'Hello, ")

child.interact()

However, it swallows the prompt and only shows echo 'Hello,. I can force bash to repaint with child.sendcontrol('l'), but this only works for some shells; dash, for example, does not support it.

$ python
Python 2.7.9 (default, Dec 11 2014, 08:58:12) 
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pexpect
>>> pexpect.__version__
'3.2'

Upvotes: 1

Views: 9701

Answers (2)

jquast
jquast

Reputation: 36

Not a bug, pexpect does indeed "suppress" up until interact, as this is intended, it doesn't know you would later call interact.

Anyway. If you want to see the prompt (and anything else) printed up until the match, just print it:

#! /usr/bin/env python
from __future__ import print_function
import pexpect
child = pexpect.spawn('bash')
index = child.expect_exact("$ ")
print(child.before + child.match, end='')
child.interact()

(Be careful about matching $, not all prompts have them. If you're going to use this for any portability, you should take care to force-set PS1 and so on, an example in the pexpect.replwrap.bash() function: https://github.com/pexpect/pexpect/blob/master/pexpect/replwrap.py#L108-113 )

It has been a very long time since I used the original tcl/expect, but I seem to recall that it implies duplicating all child program output to the parent process: it always duplicates stdout, which is why the tcl/expect version doesn't require printing before interact to "see" what was given up until interact is called.

https://github.com/pexpect/pexpect/issues/184#issuecomment-78819460

Upvotes: 1

Nathaniel M. Beaver
Nathaniel M. Beaver

Reputation: 755

As J.F. Sebastian indicated, there is an alternative:

#! /usr/bin/env python
import pexpect
import sys
child = pexpect.spawn('bash')
child.logfile_read = sys.stdout
index = child.expect_exact("$ ")
child.interact()

Upvotes: 2

Related Questions