Mit dem Folgenden wären Sie etwas zufriedener.
import subprocess
awk_sort = subprocess.Popen( "awk -f script.awk | sort > outfile.txt",
stdin=subprocess.PIPE, shell=True )
awk_sort.communicate( b"input data\n" )
Delegieren Sie einen Teil der Arbeit an die Shell. Lassen Sie sie zwei Prozesse mit einer Pipeline verbinden.
Sie wären viel glücklicher, wenn Sie "script.awk" in Python umschreiben und damit awk und die Pipeline eliminieren könnten.
bearbeiten . Einige der Gründe für die Annahme, dass awk nicht hilfreich ist.
(Es gibt zu viele Gründe, um über Kommentare zu antworten.)
-
Awk fügt einen Schritt ohne nennenswerten Wert hinzu. Es gibt nichts Einzigartiges an der Verarbeitung von Awk, das Python nicht beherrscht.
-
Das Pipelining von awk zu sort kann bei großen Datenmengen die verstrichene Verarbeitungszeit verbessern. Bei kleinen Datenmengen hat es keinen signifikanten Vorteil. Eine schnelle Messung von awk >file ; sort file
y awk | sort
wird von Gleichzeitigkeit hilft offenbaren. Bei der Sortierung hilft sie nur selten, da die Sortierung kein Durchgangsfilter ist.
-
Die Einfachheit der "Python to sort"-Verarbeitung (anstelle von "Python to awk to sort") verhindert genau die Art von Fragen, die hier gestellt werden.
-
Python ist zwar wortreicher als awk, aber auch explizit, während awk bestimmte implizite Regeln hat, die für Neulinge undurchsichtig und für Nicht-Spezialisten verwirrend sind.
-
Awk fügt (wie das Shell-Skript selbst) eine weitere Programmiersprache hinzu. Wenn all dies in einer Sprache (Python) erledigt werden kann, werden durch den Wegfall der Shell und der Awk-Programmierung zwei Programmiersprachen überflüssig, so dass sich jemand auf die wertschöpfenden Teile der Aufgabe konzentrieren kann.
Unterm Strich kann awk keinen nennenswerten Mehrwert bringen. In diesem Fall ist awk ein Nettokostenfaktor; es hat genug Komplexität hinzugefügt, dass es notwendig war, diese Frage zu stellen. Das Entfernen von awk wird ein Nettogewinn sein.
Seitenleiste Warum der Bau einer Pipeline ( a | b
) ist so schwierig.
Wenn die Schale konfrontiert wird mit a | b
muss sie Folgendes tun.
-
Einen Kindprozess der ursprünglichen Shell aufspalten. Dieser wird schließlich zu b.
-
Bauen Sie ein os-Rohr. (keine Python-Subprocess.PIPE), sondern rufen Sie os.pipe()
die zwei neue Dateideskriptoren zurückgibt, die über einen gemeinsamen Puffer verbunden sind. Zu diesem Zeitpunkt hat der Prozess stdin, stdout und stderr von seinem Elternteil sowie eine Datei, die "stdout von a" und "stdin von b" sein wird.
-
Ein Kind gabeln. Das Kind ersetzt sein stdout durch das stdout des neuen a. Ausführen der a
Prozess.
-
Das Kind b schließt und ersetzt seine stdin durch die stdin des neuen b. Ausführen der b
Prozess.
-
Das Kind b wartet auf den Abschluss von a.
-
Der Elternteil wartet auf die Fertigstellung von b.
Ich denke, dass die oben genannte Methode rekursiv verwendet werden kann, um a | b | c
aber Sie müssen lange Pipelines implizit in Klammern setzen und sie so behandeln, als wären sie a | (b | c)
.
Da Python über os.pipe()
, os.exec()
y os.fork()
und Sie können die sys.stdin
y sys.stdout
gibt es eine Möglichkeit, das oben genannte in reinem Python zu tun. In der Tat können Sie vielleicht einige Abkürzungen ausarbeiten, indem Sie os.pipe()
y subprocess.Popen
.
Es ist jedoch einfacher, diesen Vorgang an die Shell zu delegieren.