2016-06-15 9 views
1

Zum Beispiel:Wie pipe ich Ausgabe von einem Python-Skript als Eingabe in ein anderes Python-Skript?

A script1.py ein Infix Expression von dem Benutzer erhält, und wandelt sie in eine Postfix Ausdruck und gibt es oder er druckt

script2.py nach stdout erhält eine Postfix-Expression von stdin und auswertet es und gibt den Wert

ich so etwas wie dies tun wollte:

python3 script1.py | python3 script2.py 

Dies allerdings nicht funktioniert, könnten Sie mir zeigen in die richtige Richtung, wie ich dies tun könnte?

EDIT -

hier sind einige weitere Details darüber, was "nicht funktioniert".

Wenn ich ausführen python3 script1.py | python3 script2.py Das Terminal fragt mich nach Eingabe für das script2.py-Programm, wenn es nach Eingabe für das script1.py-Programm fragen und diese als script2.py-Eingabe umleiten soll.

So fragt es mich, "Geben Sie einen Postfix-Ausdruck ein:", wenn es fragen sollte "Geben Sie einen Infix-Ausdruck ein:" und leiten Sie das zum Postfix-Skript um.

+0

was ist falsch, wenn Sie sie als Funktion setzen und sie nur nacheinander aufrufen. Dein Weg sollte übrigens funktionieren, das Problem muss deine de/serialisierung sein. – HuStmpHrrr

+1

Diese Befehlszeile sollte genau das tun, was Sie sagen, dass Sie wollen. Wie wird es Ihren Erwartungen * nicht gerecht * gerecht? ("Es funktioniert nicht" ist ein vollständig informationsfreier Problembericht.) – rici

+0

Es ist nichts falsch daran, die Skripte als zwei separate Funktionen zu definieren und sie nacheinander aufzurufen, aber ich möchte lernen, wie man das macht. Was die De/Serialisierung angeht, könnten Sie das näher ausführen? – 7alman

Antwort

0

Wenn ich Ihr Problem richtig verstehe, schreiben Ihre beiden Skripte jeweils eine Eingabeaufforderung aus. Zum Beispiel könnten sie beide so etwas wie diese:

in_string = input("Enter something") 
print(some_function(in_string)) 

Wo some_function ist eine Funktion, die unterschiedlichen Ausgang in Abhängigkeit von der Eingabezeichenfolge hat (das in jedem Skript verschieden sein kann). Das Problem ist, dass die Eingabeaufforderung "Enter something" dem Benutzer nicht richtig angezeigt wird, wenn die Ausgabe eines Skripts an ein anderes Skript weitergeleitet wird. Das liegt daran, dass die Eingabeaufforderung in die Standardausgabe geschrieben wird. Daher wird die Eingabeaufforderung des ersten Skripts an das zweite Skript weitergeleitet, während die Eingabeaufforderung für das zweite Skript angezeigt wird. Das ist irreführend, da es das erste Skript ist, das (direkt) Eingaben vom Benutzer erhält. Der Eingabetext kann auch die Daten verwirren, die zwischen den beiden Skripten übergeben werden.

Es gibt keine perfekte Lösung für dieses Problem. Eine Teillösung besteht darin, die Eingabeaufforderung anstelle der Standardausgabe auf Standardfehler zu schreiben. Auf diese Weise können Sie beide Eingabeaufforderungen sehen (obwohl Sie nur auf einen von ihnen reagieren könnten).Ich glaube nicht, dass Sie direkt, dass mit input tun können, aber print kann in anderen Dateiströmen schreiben, wenn Sie wollen: print("prompt", file=sys.stderr)

Eine weitere Teillösung ist, wenn Sie Ihre Eingabe und Ausgabeströme zu überprüfen und überspringen Sie die Anweisungen drucken, wenn entweder eine ist kein "tty" (Terminal). In Python können Sie sys.stdin.isatty() tun. Viele Befehlszeilenprogramme haben einen anderen "interaktiven Modus", wenn sie direkt mit dem Benutzer und nicht mit einer Pipe oder einer Datei verbunden sind.

Wenn das Umleiten der Ausgabe ein Hauptmerkmal Ihres Programms ist, möchten Sie möglicherweise keine Eingabeaufforderungen verwenden! Viele Standard-Unix-Befehlszeilenprogramme (wie cat und grep) haben überhaupt kein interaktives Verhalten. Sie erfordern, dass der Benutzer Befehlszeilenargumente übergibt oder Umgebungsvariablen festlegt, um zu steuern, wie sie ausgeführt werden. Dadurch können sie wie erwartet arbeiten, selbst wenn sie keinen Zugriff auf Standardeingabe und Standardausgabe haben.

0

Zum Beispiel, wenn Sie nginx Laufen und script1.py haben:

import os 

os.system("ps aux") 

und script2.py

import os 

os.system("grep nginx") 

Dann läuft:

python script1.py | script2.py 

wird gleich wie

0

Aus Gründen der Vollendung, und eine Alternative zu bieten os Modul zu verwenden:

Das fileinput Modul kümmert sich um Rohrleitungen für Sie, und aus einem einfachen Test läuft ich es glauben, es wird eine einfache Implementierung machen.

Ihre Dateien zu aktivieren verrohrt Eingang zu unterstützen, dies einfach tun:

import fileinput 
with fileinput.input() as f_input: # This gets the piped data for you 
    for line in f_input: 
     # do stuff with line of piped data 

alles, was Sie dann tun müssen, würde:

$ some_textfile.txt | ./myscript.py 

Beachten Sie, dass die Dateneingabe auch für Ihre ermöglicht FileInput- Skripte wie so: $ ./myscript.py some_textfile.txt $ ./myscript.py < some_textfile.txt

Thi s arbeitet mit Druckausgabe des Pythons genauso einfach:

>test.py # This prints the contents of some_textfile.txt 
with open('some_textfile.txt', 'r') as f: 
    for line in f: 
     print(line) 

$ ./test.py | ./myscript.py 

Natürlich nicht zu vergessen die Hash-Bang #!/usr/bin/env python an der Spitze Ihrer Skripte für diese Art und Weise zu arbeiten.

Das Rezept wird in Beazley & Jones's Python Cookbook vorgestellt - ich kann es von ganzem Herzen empfehlen.

Verwandte Themen