Ich versuche einige der Code-Golf Herausforderungen zu meistern, aber alle erfordern die Eingabe von stdin
. Wie bekomme ich das in Python?
Sie können das Modul fileinput
verwenden:
import fileinput
for line in fileinput.input():
pass
fileinput
durchläuft alle Zeilen in der Eingabe, die als Dateinamen in Befehlszeilenargumenten angegeben sind, oder die Standardeingabe, wenn keine Argumente angegeben werden.
Hinweis: line
enthält eine nachgestellte Zeile. Verwenden Sie line.rstrip()
, um es zu entfernen.
Dafür gibt es mehrere Möglichkeiten.
sys.stdin
ist ein dateiähnliches Objekt, mit dem Sie die Funktionen read
oder readlines
aufrufen können, wenn Sie alles lesen möchten oder alles lesen und automatisch durch Zeilenumbruch teilen möchten. (Damit dies funktioniert, müssen Sie import sys
.)
Wenn Sie den Benutzer zur Eingabe von Prompt auffordern möchten, können Sie raw_input
in Python 2.X und nur input
in Python 3 verwenden.
Wenn Sie eigentlich nur Befehlszeilenoptionen lesen möchten, können Sie über die Liste sys.argv darauf zugreifen.
Sie werden wahrscheinlich diesen Wikibook-Artikel zu I/O in Python als nützliche Referenz finden.
import sys
for line in sys.stdin:
print line
Python hat auch die integrierten Funktionen input()
und raw_input()
. Siehe die Python-Dokumentation unter Eingebaute Funktionen .
Zum Beispiel,
name = raw_input("Enter your name: ") # Python 2.x
oder
name = input("Enter your name: ") # Python 3
Hier ist von Learning Python :
import sys
data = sys.stdin.readlines()
print "Counted", len(data), "lines."
Unter Unix können Sie es testen, indem Sie Folgendes tun:
% cat countlines.py | python countlines.py
Counted 3 lines.
Unter Windows oder DOS würden Sie Folgendes tun:
C:\> type countlines.py | python countlines.py
Counted 3 lines.
Die von anderen vorgeschlagene Antwort:
for line in sys.stdin:
print line
ist sehr einfach und Pythonic, aber es muss beachtet werden, dass das Skript bis EOF wartet, bevor es mit dem Durchlaufen der Eingabezeilen beginnt.
Dies bedeutet, dass tail -f error_log | myscript.py
Zeilen nicht wie erwartet verarbeitet.
Das richtige Skript für einen solchen Anwendungsfall wäre:
while 1:
try:
line = sys.stdin.readline()
except KeyboardInterrupt:
break
if not line:
break
print line
UPDATE
Aus den Kommentaren wurde klar, dass nur an Python 2 möglicherweise Pufferung beteiligt ist, so dass Sie darauf warten, dass der Puffer gefüllt wird, oder EOF, bevor der Druckaufruf ausgegeben wird.
Wie liest man in Python aus stdin?
Ich versuche, einige der Code-Golf-Herausforderungen zu lösen, aber für alle ist es erforderlich, dass die Eingabe von stdin stammt. Wie bekomme ich das in Python?
Sie können verwenden:
sys.stdin
- Ein dateiähnliches Objekt - rufen Sie sys.stdin.read()
auf, um alles zu lesen.input(Prompt)
- Übergebe ihm eine optionale Eingabeaufforderung zur Ausgabe, es liest von stdin bis zur ersten neuen Zeile, die es entfernt. Dies müsste wiederholt werden, um mehr Zeilen zu erhalten. Am Ende der Eingabe wird EOFError ausgelöst. (Zum Golfen wahrscheinlich nicht besonders geeignet.) In Python 2 ist dies rawinput(Prompt)
.open(0).read()
- In Python 3 akzeptiert open
Dateideskriptoren (Ganzzahlen, die die Ressourcen des Betriebssystems IO darstellen), und 0 ist der Deskriptor von stdin
. Es gibt ein dateiähnliches Objekt wie sys.stdin
zurück - wahrscheinlich die beste Wahl zum Golfen.open('/dev/stdin').read()
- ähnlich wie open(0)
, funktioniert unter Python 2 und 3, jedoch nicht unter Windows (oder sogar Cygwin).fileinput.input()
- Gibt einen Iterator über Zeilen in allen in sys.argv[1:]
aufgelisteten Dateien zurück oder stdin, falls nicht angegeben. Verwenden Sie wie ''.join(fileinput.input())
.Natürlich müssen sowohl sys
als auch fileinput
importiert werden.
sys.stdin
, die mit Python 2 und 3, Windows und Unix kompatibel sindSie müssen nur read
von sys.stdin
eingeben, zum Beispiel, wenn Sie Daten an stdin weiterleiten:
$ echo foo | python -c "import sys; print(sys.stdin.read())"
foo
Angenommen, Sie haben eine Datei, inputs.txt
, wir können diese Datei akzeptieren und wieder ausschreiben:
python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
Hier ist eine vollständige, leicht zu replizierende Demo, die zwei Methoden verwendet: die integrierte Funktion input
(verwenden Sie raw_input
in Python 2) und sys.stdin
. Die Daten bleiben unverändert, sodass die Verarbeitung nicht ausgeführt wird.
Zunächst erstellen wir eine Datei für Eingaben:
$ python -c "print('foo\nbar\nbaz')" > inputs.txt
Und mit dem Code, den wir bereits gesehen haben, können wir überprüfen, ob wir die Datei erstellt haben:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz
Hier ist die Hilfe zu sys.stdin.read
aus Python 3:
read(size=-1, /) method of _io.TextIOWrapper instance
Read at most n characters from stream.
Read from underlying buffer until we have n characters or we hit EOF.
If n is negative or omitted, read until EOF.
input
(raw_input
in Python 2)Die integrierte Funktion input
liest von der Standardeingabe bis zu einer neuen Zeile, die entfernt wird (in Ergänzung zu print
, die standardmäßig eine neue Zeile hinzufügt). Dies geschieht so lange, bis EOF (End Of File) angezeigt wird Löst EOFError
aus.
So können Sie input
in Python 3 (oder raw_input
in Python 2) verwenden, um von stdin zu lesen - also erstellen wir ein Python-Modul, das wir stdindemo.py nennen:
$ python -c "print('try:\n while True:\n print(input())\nexcept EOFError:\n pass')" > stdindemo.py
Und lassen Sie es uns ausdrucken, um sicherzustellen, dass es unseren Erwartungen entspricht:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo.py
try:
while True:
print(input())
except EOFError:
pass
Wieder liest input
bis zur neuen Zeile und entfernt sie im Wesentlichen von der Zeile. print
fügt eine neue Zeile hinzu. Während beide die Eingabe ändern, werden ihre Änderungen abgebrochen. (Sie ergänzen sich also im Wesentlichen gegenseitig.)
Und wenn input
das Dateiendezeichen erhält, wird EOFError ausgelöst, den wir ignorieren und dann das Programm beenden.
Und unter Linux/Unix können wir cat übermitteln:
$ cat inputs.txt | python -m stdindemo
foo
bar
baz
Oder wir können die Datei einfach von stdin umleiten:
$ python -m stdindemo < inputs.txt
foo
bar
baz
Wir können das Modul auch als Skript ausführen:
$ python stdindemo.py < inputs.txt
foo
bar
baz
Hier ist die Hilfe zu dem in Python 3 eingebauten input
:
input(Prompt=None, /)
Read a string from standard input. The trailing newline is stripped.
The Prompt string, if given, is printed to standard output without a
trailing newline before reading input.
If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError.
On *nix systems, readline is used if available.
sys.stdin
Hier erstellen wir ein Demo-Skript mit sys.stdin
. Die effiziente Möglichkeit, ein dateiähnliches Objekt zu durchlaufen, besteht darin, das dateiähnliche Objekt als Iterator zu verwenden. Die ergänzende Methode, von dieser Eingabe aus in stdout zu schreiben, besteht darin, einfach sys.stdout.write
zu verwenden:
$ python -c "print('import sys\nfor line in sys.stdin:\n sys.stdout.write(line)')" > stdindemo2.py
Drucken Sie es erneut aus, um sicherzustellen, dass es richtig aussieht:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo2.py
import sys
for line in sys.stdin:
sys.stdout.write(line)
Und umleiten der Eingaben in die Datei:
$ python -m stdindemo2 < inputs.txt
foo
bar
baz
In ein Kommando hineingegolft:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz
Da die Dateideskriptoren für stdin
und stdout
0 bzw. 1 sind, können wir diese auch in Python 3 an open
übergeben (nicht an 2, und beachten Sie, dass wir immer noch das 'w' zum Schreiben in stdout benötigen).
Wenn dies auf Ihrem System funktioniert, werden mehr Zeichen entfernt.
$ python -c "open(1,'w').write(open(0).read())" < inputs.txt
baz
bar
foo
Der io.open
von Python 2 erledigt dies ebenfalls, aber der Import nimmt viel mehr Platz in Anspruch:
$ python -c "from io import open; open(1,'w').write(open(0).read())" < inputs.txt
foo
bar
baz
Ein Kommentar schlägt ''.join(sys.stdin)
vor, aber das ist eigentlich länger als sys.stdin.read () - und Python muss eine zusätzliche Liste im Speicher erstellen (so funktioniert str.join
, wenn keine Liste angegeben wird) - für den Kontrast:
''.join(sys.stdin)
sys.stdin.read()
Die Top-Antwort schlägt vor:
import fileinput
for line in fileinput.input():
pass
Da jedoch sys.stdin
die Datei-API einschließlich des Iterator-Protokolls implementiert, ist dies genau das Gleiche:
import sys
for line in sys.stdin:
pass
Eine andere Antwort schlägt dies vor . Denken Sie daran, dass Sie dies in einem Dolmetscher tun müssen Ctrl-d wenn Sie unter Linux oder Mac arbeiten, oder Ctrl-z unter Windows (nach Enter), um das Dateiendezeichen an den Prozess zu senden. Diese Antwort schlägt auch print(line)
vor, das am Ende einen '\n'
hinzufügt. Verwenden Sie stattdessen print(line, end='')
(wenn Sie in Python 2 from __future__ import print_function
benötigen).
Der eigentliche Anwendungsfall für fileinput
ist das Einlesen einer Reihe von Dateien.
Dies gibt die Standardeingabe an die Standardausgabe an:
import sys
line = sys.stdin.readline()
while line:
print line,
line = sys.stdin.readline()
Aufbauend auf allen Antworten, die sys.stdin
verwenden, können Sie Folgendes tun, um aus einer Argumentdatei zu lesen, wenn mindestens ein Argument vorhanden ist, und ansonsten auf stdin zurückzugreifen:
import sys
f = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin
for line in f:
# Do your stuff
und verwenden Sie es als entweder
$ python do-my-stuff.py infile.txt
oder
$ cat infile.txt | python do-my-stuff.py
oder auch
$ python do-my-stuff.py < infile.txt
Das würde dazu führen, dass sich Ihr Python-Skript wie viele GNU/Unix-Programme wie cat
, grep
und sed
verhält.
Der folgende Code-Code hilft Ihnen dabei (er liest alle stdin-Blockierungen in EOF
in einem String):
import sys
input_str = sys.stdin.read()
print input_str.split()
argparse
ist eine einfache LösungBeispielkompatibel mit beiden Python-Versionen 2 und 3:
#!/usr/bin/python
import argparse
import sys
parser = argparse.ArgumentParser()
parser.add_argument('infile',
default=sys.stdin,
type=argparse.FileType('r'),
nargs='?')
args = parser.parse_args()
data = args.infile.read()
Sie können dieses Skript auf verschiedene Arten ausführen:
1. Verwendung von stdin
echo 'foo bar' | ./above-script.py
oder kürzer durch Ersetzen von echo
durch hierstring :
./above-script.py <<< 'foo bar'
2. Verwenden eines Dateinamenarguments
echo 'foo bar' > my-file.data
./above-script.py my-file.data
3. Verwendung von stdin
durch den speziellen Dateinamen -
echo 'foo bar' | ./above-script.py -
Sie können aus stdin lesen und Eingaben in "data" wie folgt speichern:
data = ""
for line in sys.stdin:
data += line
Versuche dies:
import sys
print sys.stdin.read().upper()
und überprüfe es mit:
$ echo "Hello World" | python myFile.py
Ich bin ziemlich erstaunt, dass noch niemand diesen Hack erwähnt hatte:
python -c "import sys;print (''.join([l for l in sys.stdin.readlines()]))"
kompatibel mit python2 und python3
Aus sys.stdin
lesen, aber um Binärdaten unter Windows lesen zu können , müssen Sie besonders vorsichtig sein, da sys.stdin
dort im Textmodus geöffnet wird und \r\n
durch \n
ersetzt wird.
Die Lösung besteht darin, den Modus auf binär zu setzen, wenn Windows + Python 2 erkannt wird, und unter Python 3 sys.stdin.buffer
zu verwenden.
import sys
PY3K = sys.version_info >= (3, 0)
if PY3K:
source = sys.stdin.buffer
else:
# Python 2 on Windows opens sys.stdin in text mode, and
# binary data that read from it becomes corrupted on \r\n
if sys.platform == "win32":
# set sys.stdin to binary mode
import os, msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
source = sys.stdin
b = source.read()
Das Problem habe ich mit Lösung
import sys
for line in sys.stdin:
print(line)
wenn Sie keine Daten an stdin übergeben, wird dies für immer blockieren. Deshalb liebe ich diese Antwort : Überprüfe zuerst, ob es einige Daten zu stdin gibt, und lies sie dann. Das habe ich am Ende getan:
import sys
import select
# select(files to read from, files to write to, magic, timeout)
# timeout=0.0 is essential b/c we want to know the asnwer right away
if select.select([sys.stdin], [], [], 0.0)[0]:
help_file_fragment = sys.stdin.read()
else:
print("No data passed to stdin", file=sys.stderr)
sys.exit(2)
Ich hatte einige Probleme, als ich das lesen konnte, um die dazugehörigen Sockets zu lesen. Als der Socket geschlossen wurde, gab er in einer aktiven Schleife einen leeren String zurück. Also das ist meine Lösung dafür (was ich nur in Linux getestet habe, hoffe aber, dass es in allen anderen Systemen funktioniert)
import sys, os
sep=os.linesep
while sep == os.linesep:
data = sys.stdin.readline()
sep = data[-len(os.linesep):]
print '> "%s"' % data.strip()
Wenn Sie also anfangen, einen Socket zu hören, funktioniert er ordnungsgemäß (z. B. in Bash):
while :; do nc -l 12345 | python test.py ; done
Und Sie können es mit Telnet anrufen oder einfach einen Browser auf localhost richten: 12345
Was das betrifft:
for line in sys.stdin:
Ich habe es gerade auf Python 2.7 (dem Vorschlag eines anderen) für eine sehr große Datei ausprobiert, und ich empfehle es nicht, gerade aus den oben genannten Gründen (es passiert lange nichts).
Ich habe eine etwas mehr Pythonic-Lösung erhalten (und funktioniert mit größeren Dateien):
with open(sys.argv[1], 'r') as f:
for line in f:
Dann kann ich das Skript lokal ausführen als:
python myscript.py "0 1 2 3 4..." # can be a multi-line string or filename - any std.in input will work
Es gibt os.read(0, x)
, die xbytes von 0 liest, was stdin darstellt. Dies ist ein ungepufferter Lesevorgang, der niedriger ist als der von sys.stdin.read ().
Wenn Sie den Befehl -c
als knifflige Methode verwenden, können Sie anstelle des Befehls stdin
(und in einigen Fällen flexibler) auch einen Shell-Skriptbefehl an Ihren Befehl python übergeben indem Sie den sell-Befehl in Anführungszeichen setzen, die durch das $
-Zeichen beginnen.
z.B.
python3 -c "import sys; print(len(sys.argv[1].split('\n')))" "$(cat ~/.goldendict/history)"
Dadurch wird die Anzahl der Zeilen aus der Verlaufsdatei von goldendict gezählt.
Für Python 3 wäre das:
# Filename e.g. cat.py
import sys
for line in sys.stdin:
print(line, end="")
Dies ist im Grunde eine einfache Form von cat (1), da nicht nach jeder Zeile eine neue Zeile eingefügt wird. Sie können dies verwenden (nachdem Sie die ausführbare Datei mit chmod +x cat.py
markiert haben, z. B .:
echo Hello | ./cat.py
n = int(raw_input())
for i in xrange(n):
name, number = raw_input().split()