如何在 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 <filename> result
,您并没有传递文件标准输入,而是将文件作为参数传递。您可以从sys.argv
获取参数列表。
如果我使用 $ my_Python_script < data > result
而不使用所有 subprocess
东西,它可以很好地处理标准输入和输出,所以我认为文件参数不是这里的问题。事实上,如果我忽略了重定向,那么for
循环就会挂起,等待标准输入。我只是想弄清楚如何将subprocess
的流程实例合并到这个脚本中。
@AlexReynolds,此命令是否等同于您提供的命令? cat data | my_Python_script > result
。只是为了消除混乱。以上是关于如何在 Python 中执行将数据写入标准输入的进程?的主要内容,如果未能解决你的问题,请参考以下文章