在Python

时间:2018-01-01 13:31:46

标签: bash python-2.7 subprocess macos-high-sierra

以下的想法是使用Bash从Python中选择,例如:使用Bash select来获取用户的输入,与Bash脚本通信以获取用户选择并在Python代码中使用它。请告诉我它是否至少可能。

拥有以下简单的Bash脚本:

#!/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

它独立运作 现在我试着用Python调用它:

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

它什么都不做。没有输出,没有选择。 我正在使用High Sierra MacOS,PyCharm和Python 2.7。

PS 经过一些阅读和实验后,结果如下:

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

它的行为与我预期的一样,用户可以选择'目标'只需输入数字即可。我的错误是我忘记了冲洗。

PPS 该解决方案适用于MacOS X High Sierra,遗憾的是它不适用于Debian Jessie抱怨以下内容:

bash: /tmp/tmpdTv4hp: Text file busy

我相信这是因为`用tempfile.NamedTemporaryFile'保持临时文件打开,这以某种方式阻止Bash使用它。这使得整个想法毫无用处。

1 个答案:

答案 0 :(得分:0)

Python正在您的终端或控制台和您正在启动的(非交互!)Bash进程之间。此外,您无法将标准输出管道定向到任何位置,因此subprocess.communicate()实际上无法捕获标准错误(如果可能,您将无法看到脚本的菜单)。

以编程方式运行交互式流程是一个非常重要的场景;你会想看看pexpect或者只是在Python中实现你自己的select命令 - 我怀疑这将是最简单的解决方案(如果你能找到一个现有的库,那将是非常简单的)