运行包含管道的命令行并将结果显示到STDOUT

spu*_*ATX 38 python command-line pipe

如何从包含管道并捕获输出的Python调用shell命令?

假设命令是这样的:

cat file.log | tail -1
Run Code Online (Sandbox Code Playgroud)

Perl相当于我想做的事情就像:

my $string = `cat file.log | tail -1`;
Run Code Online (Sandbox Code Playgroud)

unu*_*tbu 51

使用subprocess.PIPE,如子流程文档部分"替换shell管道"中所述:

import subprocess
p1 = subprocess.Popen(["cat", "file.log"], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["tail", "-1"], stdin=p1.stdout, stdout=subprocess.PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
output,err = p2.communicate()
Run Code Online (Sandbox Code Playgroud)

或者,使用该sh模块,管道成为功能组合:

import sh
output = sh.tail(sh.cat('file.log'), '-1')
Run Code Online (Sandbox Code Playgroud)

  • 哇.比Perl方式简洁得多. (3认同)

ret*_*ile 7

import subprocess
task = subprocess.Popen("cat file.log | tail -1", shell=True, stdout=subprocess.PIPE)
data = task.stdout.read()
assert task.wait() == 0
Run Code Online (Sandbox Code Playgroud)

请注意,这不会捕获stderr.如果你想捕获stderr,你还需要使用task.communicate(); 如果stderr的缓冲区填满task.stdout.read(),则调用然后task.stderr.read()可以死锁.如果要将它们组合在一起,则应该能够将其2>&1用作shell命令的一部分.

但鉴于你的具体情况,

task = subprocess.Popen(['tail', '-1', 'file.log'], stdout=subprocess.PIPE)
data = task.stdout.read()
assert task.wait() == 0
Run Code Online (Sandbox Code Playgroud)

根本不需要管道.


cho*_*own 5

这个:

import subprocess
p = subprocess.Popen("cat file.log | tail -1", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
#for shell=False use absolute paths
p_stdout = p.stdout.read()
p_stderr = p.stderr.read()
print p_stdout
Run Code Online (Sandbox Code Playgroud)

或这应该工作:

import os
result = os.system("cat file.log | tail -1")
Run Code Online (Sandbox Code Playgroud)