arod
arod

Reputation: 14102

Python's sh module - is it at all possible for a script to request input?

Using Python's sh, I am running 3rd party shell script that requests my input (not that it matters much, but to be precise, I'm running an Ansible2 playbook with the --step option)

As an oversimplification of what is happening, I built a simple bash script that requests an input. I believe that if make this simple example work I can make the original case work too.

So please consider this bash script hello.sh:

#!/bin/bash

echo "Please input your name and press Enter:"
read name
echo "Hello $name"

I can run it from python using sh module, but it fails to receive my input...

import errno
import sh

cmd = sh.Command('./hello.sh')

for line in cmd(_iter=True, _iter_noblock=True):
    if line == errno.EWOULDBLOCK:
        pass
    else:
        print(line)

How could I make this work?

Upvotes: 1

Views: 1782

Answers (2)

arod
arod

Reputation: 14102

After following this tutorial, this works for my use case:

#!/usr/bin/env python3

import errno
import sh
import sys


def sh_interact(char, stdin):
    global aggregated
    sys.stdout.write(char)
    sys.stdout.flush()
    aggregated += char
    if aggregated.endswith(":"):
        val = input()
        stdin.put(val + "\n")


cmd = sh.Command('./hello.sh')
aggregated = ""

cmd(_out=sh_interact, _out_bufsize=0)

For example, the output is:

$ ./testinput.py
Please input your name and press Enter:arod

Hello arod

Upvotes: 2

Ganesh Kathiresan
Ganesh Kathiresan

Reputation: 2088

There are two ways to solve this:

  1. Using _in:

using _in, we can pass a list which can be taken as input in the python script

cmd = sh.Command('./read.sh')
stdin = ['hello']
for line in cmd(_iter=True, _iter_noblock=True, _in=stdin):
    if line == errno.EWOULDBLOCK:
        pass
    else:
        print(line)
  1. Using command line args if you are willing to modify the script.

Upvotes: 0

Related Questions