it-swarm.com.de

ausführen einer Befehlszeile mit Pipes und Anzeige des Ergebnisses an STDOUT

Wie würde man einen Shell-Befehl von Python aus aufrufen, der eine Pipe enthält und die Ausgabe aufnimmt? 

Angenommen, der Befehl lautete wie folgt:

cat file.log | tail -1

Das Perl-Äquivalent dessen, was ich versuche, wäre etwa so:

my $string = `cat file.log | tail -1`;
33
spudATX

Verwenden Sie einen Subprozess.PIPE, wie im Abschnitt "Subprozessdokumente" "Shell-Pipeline ersetzen" beschrieben:

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()

Oder mit dem Modul sh wird das Piping zu Zusammensetzung der Funktionen :

import sh
output = sh.tail(sh.cat('file.log'), '-1')
44
unutbu
import subprocess
task = subprocess.Popen("cat file.log | tail -1", Shell=True, stdout=subprocess.PIPE)
data = task.stdout.read()
assert task.wait() == 0

Beachten Sie, dass dies nicht stderr erfasst. Und wenn Sie auch stderr erfassen möchten, müssen Sie task.communicate() verwenden. Der Aufruf von task.stdout.read() und dann task.stderr.read() kann zu einem Deadlock führen, wenn der Puffer für stderr gefüllt ist. Wenn Sie möchten, dass sie kombiniert werden, sollten Sie 2>&1 als Teil des Shell-Befehls verwenden können.

Aber angesichts Ihres genauen Falls,

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

vermeidet die Notwendigkeit für das Rohr überhaupt.

7
retracile

Diese:

import subprocess
p = subprocess.Popen("cat file.log | tail -1", Shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
#Try Shell=True if the above doesn't work with Shell=False
p_stdout = p.stdout.read()
p_stderr = p.stderr.read()
print p_stdout

Oder das sollte funktionieren: 

import os
result = os.system("cat file.log | tail -1")
1
chown

Eine andere Art und Weise wie Popen wäre:

command=r"""cat file.log | tail -1 """
output=subprocess.check_output(command, Shell=True)
1
XAVI

Dies ist eine Abzweigung von @chown mit einigen Verbesserungen: 

  • ein Alias ​​für import subprocess erleichtert das Einstellen von Parametern
  • wenn Sie nur die Ausgabe wünschen, müssen Sie beim Aufruf von stderr nicht stdin oder Popen setzen.
  • für eine bessere Formatierung wird empfohlen, die Ausgabe zu decodieren
  • Shell=True ist notwendig, um einen Interpreter für die Kommandozeile aufzurufen 

#!/usr/bin/python3

import subprocess as sp

p = sp.Popen("cat app.log | grep guido", Shell=True, stdout=sp.PIPE)

output = p.stdout.read()
print(output.decode('utf-8'))

$ cat app.log 
2017-10-14 22:34:12, User Removed [albert.wesker]
2017-10-26 18:14:02, User Removed [alexei.ivanovich] 
2017-10-28 12:14:56, User Created [ivan.leon]
2017-11-14 09:22:07, User Created [guido.rossum]

$ python3 subproc.py 
2017-11-14 09:22:07, User Created [guido.rossum]
0
ivanleoncz

Einfache Funktion zum Ausführen des Shell-Befehls mit vielen Pipes

sing

res, err = eval_Shell_cmd('pacman -Qii | grep MODIFIED | grep -v UN | cut -f 2')

Funktion

import subprocess


def eval_Shell_cmd(command, debug=False):
    """
    Eval Shell command with pipes and return result
    :param command: Shell command
    :param debug: Debug flag
    :return: Result string
    """
    processes = command.split(' | ')

    if debug:
        print('Processes:', processes)

    for index, value in enumerate(processes):
        args = value.split(' ')

        if debug:
            print(index, args)

        if index == 0:
            p = subprocess.Popen(args, stdout=subprocess.PIPE)
        else:
            p = subprocess.Popen(args, stdin=p.stdout, stdout=subprocess.PIPE)

        if index == len(processes) - 1:
            result, error = p.communicate()
            return result.decode('utf-8'), error
0
phpusr