繁体   English   中英

用 python 子进程响应 bash 中的交互程序

[英]Responding to interactive programs in bash with python subprocess

我有 bash 脚本,如下所示。 当您运行它时,它会询问您的姓名,然后向您打招呼:

#example.sh
printf "Hello, who is running this program? "

read -r USERNAME

echo Hi $USERNAME!

在此处输入图像描述

是否可以编写一个 python 脚本,它可以1.运行sh example.sh 2.响应python到提示输入名称,以及3.阅读Hi Larry! 回到 python?

只是为了澄清这是一种假设情况,因此修改 bash 脚本不是目标。 谢谢!

如果您知道外部脚本的所有答案,那么您可以使用subprocess.run()并将所有答案(使用\n )作为一个字符串发送。

对于测试,我使用等待两个值USERNAMECOLOR的脚本

#example.sh
printf "Hello, who is running this program? "

read -r USERNAME

echo Hi $USERNAME!

printf "What is your favorite color? "

read -r COLOR

echo I like $COLOR too!

我可以使用单个字符串"Larry\nBlue\n"一次发送两个值。

import subprocess

cmd = ['sh', 'example.sh']

p = subprocess.run(cmd, input="Larry\nBlue\n".encode(), stdout=subprocess.PIPE)

print( p.stdout.decode() )

它在开始时发送所有内容,外部脚本将第一行作为第一个答案,第二行作为第二个答案,等等。当它完成时,Python 可以获得所有 output -

Hello, who is running this program? Hi Larry!
What is your favorite color? I like Blue too!

并且您可能必须删除不需要的元素。


但是,如果需要从外部脚本的第一个答案中获取 output 来决定发送什么作为下一个答案,那么就会出现问题。

它需要subprocess.Popen()来运行,同时发送输入并读取 output。 但还有其他问题。 如果外部脚本使用\n发送行,那么您可以使用readline()读取它,但如果它不发送\nreadline()将等待\n并且它将阻止 Python 代码。 如果它发送一行,但您将尝试读取 2 行,情况也是如此。 第二个readline()将阻止它。 所以你必须知道它发送了多少行。

如果你使用read()那么它会等待数据结束并且它也会阻塞 Python。 If you use read(100) and output will have 100 bytes (or more) then it will read 100 bytes (and rest will wait for next read() - but if it will have 99 bytes then read(100) will block Python.

您必须知道要读取多少字节,或者您必须知道它可以发送什么文本,然后您可以read(1) ,将其添加到缓冲区,并检查缓冲区是否具有您期望的字符串。 这种方法使用了expectpyexpect


readline()的第一个示例

我在printf中使用example.sh\n

printf "Hello, who is running this program? \n"

read -r USERNAME

echo Hi $USERNAME!

printf "What is your favorite color? \n"

read -r COLOR

echo I like $COLOR too!

因为example.sh\n发送所以我删除了\n

import subprocess

cmd = ['sh', 'example.sh']

p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    
print('1 >>>', p.stdout.readline().decode().rstrip(), '<<<')
p.stdin.write("Larry!\n".encode())
p.stdin.flush()
print('2 >>>', p.stdout.readline().decode().rstrip(), '<<<')

print('1 >>>', p.stdout.readline().decode().rstrip(), '<<<')
p.stdin.write("Blue!\n".encode())
p.stdin.flush()
print('2 >>>', p.stdout.readline().decode().rstrip(), '<<<')

结果:

1 >>> Hello, who is running this program? <<<
2 >>> Hi Larry!! <<<
1 >>> What is your favorite color? <<<
2 >>> I like Blue! too! <<<

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM