0

The idea of the following was to use Bash's select from Python, e.g. use Bash select to get the input from the user, communicate with the Bash script to get the user selections and use it afterwords in the Python code. Please tell me if it at least possible.

Have the following simple Bash script:

#!/bin/bash -x
function select_target {
    target_list=("Target1" "Target2" "Target3")
    PS3="Select Target: "
    select target in "${target_list[@]}"; do
        break
    done
    echo $target
}
select_target

it works standalone Now I tried to call it from Python like this:

import tempfile
import subprocess

select_target_sh_func = """
#!/bin/bash
function select_target {
    target_list=(%s)
    PS3="Select Target: "
    select target in "${target_list[@]}"; do
        break
    done
    echo $target
}
select_target
"""

target_list = ["Target1", "Target2", "Target3"]

with tempfile.NamedTemporaryFile() as temp:
    temp.write(select_target_sh_func % ' '.join(map(lambda s : '\"%s\"' % str(s),target_list)))
    subprocess.call(['chmod', '0777', temp.name])

    sh_proc = subprocess.Popen(["bash", temp.name], stdout=subprocess.PIPE)
    (output, err) = sh_proc.communicate()
    exit_code = sh_proc.wait()
    print output

It does nothing. No output, no selection. I'm using High Sierra MacOS, PyCharm and Python 2.7.

PS After some reading and experimenting ended up with the following:

with tempfile.NamedTemporaryFile() as temp:
    temp.write(select_target_sh_func % ' '.join(map(lambda s : '\"%s\"' % str(s),target_list)))
    temp.flush()
    # bash: /var/folders/jm/4j4mq_w52bx2l5qwg4gt44580000gn/T/tmp00laDV: Permission denied
    subprocess.call(['chmod', '0500', temp.name])
    sh_proc = subprocess.Popen(["bash", "-c", temp.name], stdout=subprocess.PIPE)
    (output, err) = sh_proc.communicate()
    exit_code = sh_proc.wait()
    print output

It behaves as I expected it would, the user is able to select the 'target' by just typing the number. My mistake was that I forgot to flush.

PPS The solution works for MacOS X High Sierra, sadly it does not for Debian Jessie complaining the following:

bash: /tmp/tmpdTv4hp: Text file busy

I believe it is because `with tempfile.NamedTemporaryFile' keeps the temp file open and this somehow prevents Bash from working with it. This renders the whole idea useless.

  • This might help: [Embed bash in python](https://stackoverflow.com/q/2651874/3776858) – Cyrus Jan 01 '18 at 13:39
  • I did it almost identical. After fixing some minor differences still no output, no selection as if the bash script ain't run – Vladimir Zolotykh Jan 01 '18 at 14:10
  • Whatever you are attempting to accomplish, **`chmod 0777` is *horribly wrong*** and a **serious security problem.** Figure out what permissions you need, and assign those instead; you will **absolutely never** need to give every user on the system write access to code you are about to execute. For this particular scenario, you probably only need to give *yourself* execute permission. – tripleee Jan 01 '18 at 15:03

1 Answers1

0

Python is sitting between your terminal or console and the (noninteractive!) Bash process you are starting. Furthermore, you are failing to direct the standard output pipe anywhere, so subprocess.communicate() actually cannot capture standard error (and if it could, you would not be able to see the script's menu).

Running an interactive process programmatically is a nontrivial scenario; you'll want to look at pexpect or just implement your own select command in Python - I suspect this is going to turn out to be the easiest solution (trivially so if you can find an existing library).

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Quick googling got me https://github.com/jonathanslenders/python-prompt-toolkit/ but I have no experience with this. – tripleee Jan 01 '18 at 15:16
  • I did 'select' in Python firstly. Attractiveness of the Bash select for me is that that it nicely formats a table with choices when they are many. – Vladimir Zolotykh Jan 01 '18 at 18:01