Search code examples
pythonbashshellautomationcommand-prompt

python dynamically answer yes/no to terminal prompt


prompt question generator

class SynthesisPromptGenerator:
    def wait_key(self):
        ''' Wait for a key press on the console and return it. '''
        result = None

        for singlePrompt in ["questionCat", "questionDog"]:
            try:
                result = raw_input(singlePrompt)
                print 'input is: ', result
            except IOError:
                pass

        return result

I have a PromptGenerator that will generate multiple terminal prompt questions, and after answering first question, then second will pop up, as

questionCat
(and wait for keyboard input)

questionDog
(and wait for keyboard input)

my goal is to automatically and dynamically answer to the questions

class PromptResponder:
    def respond(self):
        generator = SynthesisPromptGenerator()
        child = pexpect.spawn(generator.wait_key())

        child.expect("\*Cat\*")
        child.sendline("yes")
        child.expect("\*Dog\*")
        child.sendline("no")
        child.expect(pexpect.EOF)


if __name__ == "__main__":
    responder = PromptResponder()
    responder.respond()
  • if the prompt question contains Cat then answer yes
  • if the prompt question contains Dog then answer no

So it comes to:

  1. how to get the prompt string from terminal and filter based on it?
  2. how to answer multiple prompt questions in python?

I did some search but found most questions are for shell script echo yes | ./script, not much doing it in python

thank you very much


Solution

  • As suggested in the comments, use pexpect.

    See pexpect on github, the official docs and this handy python for beginners walkthrough on pexpect.

    For an example. Let's say this is your x.sh file:

    #!/bin/bash
    
    echo -n "Continue? [Y/N]: "
    read answer
    if [ "$answer" != "${answer#[Yy]}" ]; then
            echo -n "continuing.."
    else
            echo -n "exiting.."
    fi
    

    You can do this:

    import os, sys
    import pexpect
    
    # It's probably cleaner to use an absolute path here
    # I just didn't want to include my directories..
    # This will run x.sh from your current directory.
    child = pexpect.spawn(os.path.join(os.getcwd(),'x.sh'))
    child.logfile = sys.stdout
    # Note I have to escape characters here because
    # expect processes regular expressions.
    child.expect("Continue\? \[Y/N\]: ")
    child.sendline("Y")
    child.expect("continuing..")
    child.expect(pexpect.EOF)
    print(child.before)
    

    Result of the python script:

    Continue? [Y/N]: Y
    Y
    continuing..
    

    Although I have to say that it's a bit unusal to use pexpect with a bash script if you have the ability to edit it. It would be simpler to edit the script so that it no longer prompts:

    #!/bin/bash
    
    echo -n "Continue? [Y/N]: "
    answer=y
    if [ "$answer" != "${answer#[Yy]}" ]; then
            echo "continuing.."
    else
            echo "exiting.."
    fi
    

    Then you're free to just use subprocess to execute it.

    import os
    import subprocess
    
    subprocess.call(os.path.join(os.getcwd(),"x.sh"))
    

    Or if you want the output as a variable:

    import os
    import subprocess
    
    p = subprocess.Popen(os.path.join(os.getcwd(),"x.sh"), stdout=subprocess.PIPE)
    out, error = p.communicate()
    
    print(out)
    

    I realise this might not be possible for you but it's worth noting.