如何在 Python 中执行将数据写入标准输入的进程?

Posted

技术标签:

【中文标题】如何在 Python 中执行将数据写入标准输入的进程?【英文标题】:How to execute process in Python where data is written to stdin? 【发布时间】:2013-02-24 16:43:27 【问题描述】:

我的 Python 脚本中有一个标志,它指定我是否设置和使用外部进程。这个过程是一个名为my_command 的命令,它从标准输入中获取数据。如果我要在命令行上运行它,它会是这样的:

$ my_command < data > result

我想使用 Python 脚本通过修改标准输入并将其提供给 my_command 来生成 data 行。

我正在做这样的事情:

import getopt, sys, os, stat, subprocess

# for argument's sake, let's say this is set to True for now
# in real life, I use getopt.getopt() to decide whether this is True or False
useProcess = True

if useProcess:
    process = subprocess.Popen(['my_command'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

for line in sys.stdin:
    # parse line from standard input and modify it
    # we store the result in a variable called modified_line
    modified_line = line + "foo"

    # if we want to feed modified_line to my_command, do the following:
    if useProcess:
        process.stdin.write(modified_line)

    # otherwise, we just print the modified line
    else:
        print modified_line

但是,my_command 的行为就好像它没有收到任何数据并以错误状态退出。我做错了什么?

编辑

假设我的 Python 脚本名为 my_Python_script。假设我通常会通过标准输入传递 my_command 一个名为 data 的文件:

$ my_command < data > result

但现在我将其传递给my_Python_script

$ my_Python_script < data > some_other_result

我希望my_Python_script 有条件地设置一个子进程,该子进程在data 的内容上运行my_command(在传递给my_command 之前由my_Python_script 修改)。这更有意义吗?

如果我使用bash 作为脚本语言,我会有条件地决定运行两个函数之一。一种是将数据行传输到my_command。另一个不会。这可以用 Python 完成吗?

【问题讨论】:

my_command是什么文件?它是一个shell脚本吗? Python脚本?您可能想尝试类似 ['/bin/bash', 'my_command'] 或类似的 Python 脚本。 您可以将 my_python_script 写成 Unix 过滤器。然后python脚本对my_command一无所知,只是从stdin读取,以某种方式修改它,然后打印到stdout:`some_other_result 如果是stdout=PIPE,那么你应该从中读取,否则如果它产生足够的输出,进程可能会阻塞。 主进程和子进程之间双向通信的简单示例可以在这里找到:***.com/a/52841475/1349673 【参考方案1】:

写入标准输入后,需要关闭它:

    process.stdin.write(modified_line)
    process.stdin.close()

更新

我没有注意到 process.stdin.write() 是在 for 循环中执行的。在这种情况下,您应该将process.stdin.close() 移到循环之外。

另外,Raymond 提到我们也应该打电话给process.wait()。所以更新后的代码应该是:

for ...
    process.stdin.write(modified_line)

process.stdin.close()
process.wait()

【讨论】:

这会在第二次通过for 循环时引发ValueError 异常:ValueError: I/O operation on closed file。命令my_command 处理多行(实际上,它模仿了UNIX sort 的特定应用程序),所以我认为stdin 句柄需要保持打开状态。 你能在for循环之后关闭吗?我的错。【参考方案2】:

除了@HaiVu提到的process.stdin.close()之外,你有没有做process.wait()等待命令执行完成才能得到结果?

【讨论】:

我忘了process.wait()。很好的收获。【参考方案3】:

您似乎混淆了参数和标准输入。你的命令应该是

$ <data> | mycommand result

一旦调用命令就会传入数据。

使用raw_input 内置函数完成输入。 (http://docs.python.org/2/library/functions.html)

【讨论】:

我不明白。我正在尝试从脚本中传递my_command 修改后的数据,而不是让最终用户通过终端手动输入数据。一切都应该在脚本中处理。这更有意义吗? @AlexReynolds 如果您在 shell 中输入。您将如何将多行输入作为参数传递给命令?我认为你混淆了论点(即:command arg1 arg2 arg2)和标准输入(即:(echo arg1; echo arg2; echo arg3) | command。你必须解释你想要哪一个 我认为令人困惑的是,如果您调用$ python name_of_script.py &lt;filename&gt; result,您并没有传递文件标准输入,而是将文件作为参数传递。您可以从sys.argv 获取参数列表。 如果我使用 $ my_Python_script &lt; data &gt; result 而不使用所有 subprocess 东西,它可以很好地处理标准输入和输出,所以我认为文件参数不是这里的问题。事实上,如果我忽略了重定向,那么for 循环就会挂起,等待标准输入。我只是想弄清楚如何将subprocess 的流程实例合并到这个脚本中。 @AlexReynolds,此命令是否等同于您提供的命令? cat data | my_Python_script &gt; result。只是为了消除混乱。

以上是关于如何在 Python 中执行将数据写入标准输入的进程?的主要内容,如果未能解决你的问题,请参考以下文章

如何写入 Python 子进程的标准输入?

Python子进程将数据定向到标准输入

Python:如何写入子进程的标准输入并实时读取其输出

在 Rust 中写入子进程的标准输入?

如何在 linux 系统上用 PHP 启动后台进程并将用户 ajax 输入重复写入其标准输入

如何使用 coreAudio 将标准化浮点值数组写入 AIFF?