【问题标题】:Python subprocess input is read twicePython 子进程输入被读取两次
【发布时间】:2023-12-02 08:10:01
【问题描述】:

我需要在 python 中包装一个程序并提供输入和打印输出。但是,如果它给它一行输入,它似乎将其用作输入,直到程序终止。我用 C 语言编写了一个非常基本的程序(称为 inout),它接受两行输入并打印到标准输出。

from subprocess import Popen, PIPE, STDOUT

p = Popen(['inout'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
out, err = p.communicate(input=b'Why is this twice')

print(out)
print("done")

这个程序的输出是:

b'Why is this twice\r\nWhy is this twice\r\n'
done

我怎样才能阻止这种情况发生?

【问题讨论】:

  • inout 的来源是什么样的?
  • @dano 它实际上是 c++ 字符串;获取线(cin,in); cout

标签: python io subprocess stdin


【解决方案1】:

错误实际上在您的 C++ 程序中;它为它的两个打印重复使用in 变量,这意味着如果对getline 的第二次调用没有返回任何内容(在你的情况下它没有返回,因为在第一次调用之后达到了stdin 的EOF getline 调用),第一个getline 调用返回的内容将被打印两次,因为它们仍然保存在in 中。如果您稍微调整您的 C++ 程序以在两次调用 getline 之间重置 in,这很明显:

#include <iostream>
using namespace std;

int main()
{
 string in; 
 getline(cin, in); 
 cout << in << endl; 
 in = ""; // reset in
 getline(cin, in); 
 cout << in << endl;
 return 0;
}

输出:

b'Why is this twice'


done

编辑:

根据你在 cmets 中给出的要求,你想要这样的东西:

from subprocess import Popen, PIPE, STDOUT

p = Popen(['./inout'], stdout=PIPE, stdin=PIPE, stderr=STDOUT, bufsize=0)  # bufsize=0 keeps stdout from being buffered.

# Send first line to inout
p.stdin.write(b'Why is this twice\n') 

# Read first line out output
first = p.stdout.readline()
print("got {}".format(first))

# Get line from user
a = input()

# Send second line to inout
p.stdin.write('{}\n'.format(a).encode('utf-8')) 

# Read second line from inout
second = p.stdout.readline()
print('also got {}'.format(second))

p.wait()
print("done")

输出:

got b'Why is this twice\n'
sdf  # This was typed by me
b'sdf\n'
done

【讨论】:

  • Okei,这实际上修复了它。由于某种原因,原始程序在 Windows 中运行时做了它应该做的事情。无论如何,我现在有一个新问题,即程序在没有收到下一行输入的情况下终止,它只是假设它是一个空行并完成。有什么建议吗?
  • @Jens 您实际上需要通过p.communicate 将两行发送到标准输入。或者,如果您确实希望其中一个 cin 调用是交互式的,则不需要使用 p.communicate(input=...),而是直接将第一行提供给 p.stdin(使用 p.stdin.write(b'Why is this twice?')),让 Python 脚本请求第二行放在自己的标准输入上,然后将输入的行提供给子进程。然后您可以调用p.communicate() 等待子进程完成并获取其标准输出。
  • 我实际上需要在第一行之后接收子程序的输出,然后再给它第二行。您对如何执行此操作有任何意见吗?顺便说一句,感谢您迄今为止的所有帮助!
  • 太棒了,谢谢!希望我有代表支持你! :)