【问题标题】:How to use a mixture of cats and pipes in subprocess如何在子流程中使用猫和管道的混合物
【发布时间】:2015-03-19 05:26:57
【问题描述】:

我正在尝试 cat 文件的内容并将其通过管道传输到第二个 python 脚本的标准输入中,然后将其标准输出放入另一个文件中。

在命令行上看起来像这样:

cat input_file | python3 ~/Desktop/python_script.py > output_file

我在阅读了许多帖子后尝试这样做

file_input = subprocess.Popen(('cat', input_file), stdout=subprocess.PIPE)
file_output = subprocess.check_output(('python3', '~/Desktop/mdparser.py'), stdin=file_input.stdout, stdout=subprocess.PIPE)
subprocess.check_output('>','output_file',stdin = file_output.stdout)

但是第二行出现以下错误:

File "/usr/local/Cellar/python3/3.4.1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/subprocess.py", line 598, in check_output
    raise ValueError('stdout argument not allowed, it will be overridden.')
ValueError: stdout argument not allowed, it will be overridden.

【问题讨论】:

  • 您不需要也不应该使用 cat 来执行此命令。 python3 python_script.py <input_file >output_file 的效率要高得多。
  • ...因此,stdin 调用 subprocess 应直接指向输入文件的句柄。
  • ...而且,> 根本不是一个过程,所以不知道你想在那里做什么;它不应该有自己的subprocess.Popen 对象;相反,第二个进程上的stdout 应该直接指向文件句柄,而不是指向 PIPE,如果您希望它转到文件。
  • 您应该将必要的功能放入函数、类中并导入模块,而不是将其作为子进程运行。如果您不想更改脚本;您可以将sys.stdinsys.stdout 设置为文件对象并调用runpy.run_path()

标签: python-3.x pipe subprocess cat


【解决方案1】:

这应该只有一个调用,而不是三个。

exit_status = subprocess.call(
  ['python3', os.path.expanduser('~/Desktop/mdparser.py')],
  stdin=open('input_file', 'r'), stdout=open('output_file', 'w'))

波浪号扩展(~/foo)由 shell 处理;当你没有 shell 时,就像这里一样,你需要自己明确地做——这就是 os.path.expanduser 所做的。

stdout 被重定向到不同的进程或文件时,您不能使用check_output()——这就是引发异常的原因,因为Python 解释器不能同时将内容读入变量并将其直接连接到不同流程的管道中。这就是消息“将被覆盖”的含义——当您使用check_output() 时,您是在告诉 Python 解释器从管道本身读取输出,但是当您将该输出配置为不同的进程或文件。

相反,直接将输出定向到文件,然后打开文件并在完成后读取它。


不使用cat 的另一个原因是它所做的只是增加效率并限制操作。运行时:

foo <input.txt >output.txt

...或者,如果您更喜欢这种形式...

<input.txt foo >output.txt

...foo 程序直接在input.txt 上获取文件句柄,并在output.txt 上直接获取另一个文件句柄。当您不使用 cat 时,这些文件句柄才是真正的交易——可以在文件中四处寻找,这意味着如果您的程序必须返回并查看先前的内容,它可以只告诉文件句柄回去寻找不同的部分。相比之下,如果您运行cat input.txt | foo,那么foo 必须将它读取的所有内容存储在内存中,如果它正在执行的操作需要不止一次传递。

在这里使用cat 只是开销——它是一个额外的程序,它从输入文件读取并写入管道的一半,毕竟,这意味着它在管道和上下文切换到并从内核。除非您需要,否则不要使用它——例如,如果您将多个文件连接到一个流中(这是cat 的目的,因此得名)。

【讨论】:

    猜你喜欢
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 2015-02-10
    • 2011-04-01
    • 1970-01-01
    • 2015-07-02
    相关资源
    最近更新 更多