Python中subprocess.communicate疑问:输入内容为何重复输出
为什么用subprocess调用bc时输入内容会被一同输出?
你使用的代码如下:
from subprocess import Popen, PIPE, STDOUT p = Popen(['bc', '-q', '-i'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) while True: if p.poll() is None: data = input("> ") data = data + "\n" out, err = p.communicate(data.encode()) print(out.decode().rstrip()) else: break
运行时出现的现象:
> 1+2 1+2 3
原因解析
这不是communicate()函数的问题,而是bc工具交互模式(-i参数)的默认行为:当你用-i启动bc进入交互模式时,它会自动回显你输入的内容——就像在终端直接敲bc -i时,输入表达式后bc会先重复你的输入,再输出计算结果。哪怕你把stdin/stdout重定向到了管道,这个回显逻辑依然会生效,所以你会在输出里看到自己输入的内容。
另外补充一个代码逻辑问题:communicate()会一次性发送数据到子进程的stdin,然后等待子进程终止才返回结果。所以第一次调用communicate()后,bc进程会因为stdin被关闭而退出,你的循环实际上只会执行一次。
解决办法
如果不想看到输入回显,可以有两种选择:
- 去掉bc的
-i参数,用非交互模式运行:from subprocess import Popen, PIPE, STDOUT p = Popen(['bc', '-q'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) while True: data = input("> ") if not data: break out, _ = p.communicate(f"{data}\n".encode()) print(out.decode().rstrip()) - 保留交互模式,但在bc里关闭回显(设置
echo=0):from subprocess import Popen, PIPE, STDOUT p = Popen(['bc', '-q', '-i'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) # 先发送关闭回显的命令 p.communicate(b"echo=0\n") while True: if p.poll() is None: data = input("> ") out, _ = p.communicate(f"{data}\n".encode()) print(out.decode().rstrip()) else: break
内容的提问来源于stack exchange,提问作者yokeshwaran
相关产品推荐
相关产品推荐

