0

I am running Solaris 5-10, python 2.6.2 and pexpect 2.4

I have the very simple python script below which exercises the functionality of sending and receiving text from the shell.

My understanding is that pexepect([pexpect.TIMEOUT, x,y,z], timeout=w) will return the index of the match that it found since the last time pexpect was called, but if it takes longer than w seconds, it will return 0.

Here is my very simple script:

#!/usr/bin/env python 

import pexpect 
myPrompt = " % " 

myShell = pexpect.spawn("/bin/tcsh") 
print "Sending 'JUNK-0' to shell" 
x = myShell.sendline("JUNK-0") 
y = myShell.expect([pexpect.TIMEOUT], timeout=1)               
print "y = %s" % y 
print myShell.before 
print "=" * 80 
print "\n\n" 

for i in range(2): 
    print "i = %d" % (i+1) 
    print "Sending 'JUNK-%d' to shell" % (i+1) 
    x = myShell.sendline("JUNK-%d" % (i+1)) 
    y = myShell.expect([pexpect.TIMEOUT, myPrompt], timeout=10)               
    print "y = %s" % y 
    print myShell.before 
    print "=" * 80 
    print "\n\n" 

FYI, my shell prompt is "myMachine % ", however in this script I have simply used " % " to keep it generic.

When I run it, I see the following output:

Sending 'JUNK-0' to shell 
y = 0 
JUNK-0 
myMachine % JUNK-0 
JUNK-0: Command not found. 
myMachine % 
================================================================================ 



i = 1 
Sending 'JUNK-1' to shell 
y = 1 
JUNK-0 
myMachine 
================================================================================ 



i = 2 
Sending 'JUNK-2' to shell 
y = 1 
JUNK-0 
JUNK-0: Command not found. 
myMachine 
================================================================================ 

Why do I see "JUNK-0" consistently recurring in the output? It should be consumed by the first myShell.expect() statement, but it keeps showing up. Why??

Saqib Ali
  • 11,931
  • 41
  • 133
  • 272

1 Answers1

0

What happens in the example you posted is an incorrect handling of the pexpect output. When a pexpect finds something that matches the expect expression, it populates the fields before, match and after with the correct values. This quote from the pexpect documentation might help :

"After a match is found the instance attributes 'before', 'after' and 'match' will be set. You can see all the data read before the match in 'before'. You can see the data that was matched in 'after'. The re.MatchObject used in the re match will be in 'match'. If an error occurred then 'before' will be set to all the data read so far and 'after' and 'match' will be None."

In your case, the first expect yields the following results:

before : JUNK-0 myMachine

after : % JUNK-0

Please note that after will not be entirely consumed, only % will disappear. Thus, on your next expect you get:

before : JUNK-0 JUNK-0: Command not found. myMachine

after : % JUNK-1

From what I can tell, the first expect (the one that times out, which is out of the for loop) does not consume the output.

I think that if you change the line:

myShell.expect([pexpect.TIMEOUT], timeout=1)

to

myShell.expect([pexpect.TIMEOUT, myPrompt], timeout=1)

the output will sync and you'll get the correct output.

Hope this helps.

Catalin Luta
  • 711
  • 4
  • 8