it-swarm.com.de

Wie liest du von stdin?

Ich versuche einige der Code-Golf Herausforderungen zu meistern, aber alle erfordern die Eingabe von stdin. Wie bekomme ich das in Python?

1264
tehryan

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.

854
u0b34a0f6ae

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.

636
Mark Rushakoff
import sys

for line in sys.stdin:
    print line
364
user303110

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
200
Pat Notz

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.
173
Eugene Yokota

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.

91

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 openDateideskriptoren (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.

Schnelle Beispiele für sys.stdin, die mit Python 2 und 3, Windows und Unix kompatibel sind

Sie 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

dateibeispiel

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

Längere Antwort

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.

Eingebaute Funktion, 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

Dateideskriptoren zum Golfen

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

Andere Kommentare und Antworten ansprechen

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.

76
Aaron Hall

Dies gibt die Standardeingabe an die Standardausgabe an:

import sys
line = sys.stdin.readline()
while line:
    print line,
    line = sys.stdin.readline()
35
rlib

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.

30
Emil Lundberg

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()
14
Chandan Kumar

argparse ist eine einfache Lösung

Beispielkompatibel 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 -
8
olibre

Sie können aus stdin lesen und Eingaben in "data" wie folgt speichern:

data = ""
for line in sys.stdin:
    data += line
7
Wei

Versuche dies:

import sys

print sys.stdin.read().upper()

und überprüfe es mit:

$ echo "Hello World" | python myFile.py
7
Boubakr

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

6
Uri Goren

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

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)
3
SummerBreeze

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

2
estani

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
1
szeitlin

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

0
Jay

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.

0
Kasrâmvd

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
0
AdamKalisz
n = int(raw_input())
for i in xrange(n):
    name, number = raw_input().split()
0
issam