简体   繁体   English

使用subprocess.communicate()传递标准输入而不用等待进程

[英]Use subprocess.communicate() to pipe stdin without waiting for process

I need to launch a process and pipe a string in to stdin, which I am currently doing like this: 我需要启动一个进程并将一个字符串传递到stdin中,我目前正在这样做:

proc = subprocess.Popen(["MyCommandHere"], stdin=subprocess.PIPE)
proc.communicate(input=bytes(my_str_input + "\n", "ascii"))

The problem is that when I use subprocess.communicate() it is a blocking call, waiting for the process to exit. 问题是当我使用subprocess.communicate()它是一个阻塞调用,正在等待进程退出。 I do not want to wait. 我不想等。

Is there some way to get communicate() to not block, or some other way to pipe my input? 是否有某种方法可以使communicate()不被阻塞,或通过其他方式来传递我的输入? I am asking about non-blocking writes, not non-blocking reads. 我问的是非阻塞写入,而不是非阻塞读取。

Two obvious options: 两个明显的选择:

  1. Use a separate thread or process 使用单独的线程或进程
  2. Feed stdin from a temporary file 从临时文件中stdin

Option 1: 选项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()

Option 2: 选项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)

The write to the temporary file can block, but usually temporary files are optimized by the OS to minimize writes to disk when possible; 对临时文件的写操作可能会阻止,但通常操作系统会优化临时文件,以尽可能减少对磁盘的写操作。 if the process might take some time to finish, you might block too long piping directly, but the small blocking for writing out the data won't matter. 如果该过程可能需要一些时间才能完成,则可以直接阻塞太长的管道,但是用于写出数据的较小阻塞将无关紧要。 Even though Python closes the temporary file when the with block exits (which would normally cause it to be deleted), the process maintains a handle to it, preventing it from being cleaned up until the process completes. 即使Python在with块退出时关闭了临时文件(通常会导致临时文件被删除),该进程仍会维护该文件的句柄,以防止在进程完成前对其进行清理。

Note: All of this assumes the process might not consume your input completely immediately on launch. 注意:所有这些都假设该过程可能不会在启动后立即完全消耗您的输入。 If the process basically reads the input immediately, then does all its work, you can simplify to just: 如果该过程基本上立即读取了输入,然后完成了所有工作,则可以简化为:

proc.stdin.write(bytes(my_str_input + "\n", "ascii"))
proc.stdin.close()  # Ensures the process knows nothing else is coming

This just risks blocking if the process consumes the input a little at a time, and the input is larger than the pipe buffers (so you can't write it all at once). 如果进程一次消耗一点输入,并且输入大于管道缓冲区(因此您不能一次全部写出),这只会有阻塞的风险。

Take a look at the docs on Popen.stdin . 看看Popen.stdin上的文档 It's just a standard writable object (and, in most cases, a standard file handle anyway), so you can do: 它只是一个标准的可写对象(在大多数情况下,还是一个标准的文件句柄),因此您可以执行以下操作:

proc.stdin.write(bytes(...))

To write data to stdin without needing to wait for the subprocess to complete. 将数据写入标准输入而无需等待子过程完成。

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

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