我需要启动一个进程并将一个字符串传递给stdin,我目前正在这样做:
proc = subprocess.Popen(["MyCommandHere"], stdin=subprocess.PIPE)
proc.communicate(input=bytes(my_str_input + "\n", "ascii"))
问题在于,当我使用subprocess.communicate()
时,它是一个阻塞调用,等待进程退出。我不想等。
有没有办法让communicate()
不阻止,或者用其他方式管道我的输入?我问的是非阻塞写入,而不是非阻塞读取。
答案 0 :(得分:1)
两个明显的选择:
stdin
选项1:
import threading
def send_data_to(proc, inp):
proc.communicate(inp)
proc = subprocess.Popen(["MyCommandHere"], stdin=subprocess.PIPE)
threading.Thread(target=send_data_to, args=(proc, bytes(my_str_input + "\n", "ascii"))).start()
选项2:
import tempfile
with tempfile.TemporaryFile() as tf:
tf.write(bytes(my_str_input + "\n", "ascii"))
tf.flush()
tf.seek(0) # Might not be needed
proc = subprocess.Popen(["MyCommandHere"], stdin=tf)
对临时文件的写入可以阻止,但通常由OS优化临时文件,以尽可能减少对磁盘的写入;如果这个过程可能需要一些时间才能完成,你可能会直接阻塞过长的管道,但是用于写出数据的小阻塞并不重要。即使Python在with
块退出时关闭临时文件(这通常会导致它被删除),该进程会保留一个句柄,防止它在进程完成之前被清除。
注意:所有这些都假设在启动时该过程可能不会立即完全消耗您的输入。如果该过程基本上立即读取输入,那么它的所有工作都可以完成,您可以简化为:
proc.stdin.write(bytes(my_str_input + "\n", "ascii"))
proc.stdin.close() # Ensures the process knows nothing else is coming
如果进程一次消耗一点输入,并且输入大于管道缓冲区(因此你不能一次写入所有内容),这就冒了阻塞的风险。
答案 1 :(得分:0)
看看at the docs on Popen.stdin
。它只是一个标准的可写对象(在大多数情况下,无论如何都是标准的文件句柄),所以你可以这样做:
proc.stdin.write(bytes(...))
将数据写入stdin而无需等待子进程完成。