Comment lisez-vous stdin en Python?
j'essaie de faire quelques-uns des défis code golf , mais ils exigent tous l'entrée à partir de stdin
. Comment puis-je obtenir qu'en Python?
19 réponses
vous pouvez utiliser le fileinput
module:
import fileinput
for line in fileinput.input():
pass
fileinput
boucle toutes les lignes de l'entrée spécifiée en tant que noms de fichiers donnés en arguments de ligne de commande, ou l'entrée standard si aucun argument n'est fourni.
il y a plusieurs façons de le faire.
-
sys.stdin
est un objet semblable à un fichier sur lequel vous pouvez appeler les fonctionsread
oureadlines
si vous voulez tout lire ou vous voulez tout lire et le diviser par newline automatiquement. (Vous devezimport sys
pour que cela fonctionne.) -
Si vous voulez invite l'utilisateur pour l'entrée, vous peut utiliser
raw_input
en Python 2.X, et justeinput
en Python 3. -
si vous voulez simplement lire les options en ligne de commande, vous pouvez y accéder via le système .argv liste.
vous trouverez probablement cet article de Wikibook sur I/O en Python sera aussi une référence utile.
Python a également intégré les fonctions input()
et raw_input()
. Voir la documentation Python sous fonctions intégrées .
par exemple,
name = raw_input("Enter your name: ") # Python 2.x
ou
name = input("Enter your name: ") # Python 3
Ici de l'Apprentissage de Python :
import sys
data = sys.stdin.readlines()
print "Counted", len(data), "lines."
sur Unix, vous pouvez le tester en faisant quelque chose comme:
% cat countlines.py | python countlines.py
Counted 3 lines.
sous Windows ou DOS, vous feriez:
C:\> type countlines.py | python countlines.py
Counted 3 lines.
la réponse proposée par d'autres:
for line in sys.stdin:
print line
est très simple et pythonique, mais il faut noter que le script attendra EOF avant de commencer à itérer sur les lignes d'entrée.
cela signifie que tail -f error_log | myscript.py
ne traitera pas les lignes comme prévu.
Le script correct pour un tel cas d'utilisation serait:
while 1:
try:
line = sys.stdin.readline()
except KeyboardInterrupt:
break
if not line:
break
print line
mise à JOUR
D'après les commentaires, il a été clarifié que sur python 2 seulement, il pourrait y avoir des buffers impliqués, de sorte que vous finirez par attendre que le buffer se remplisse ou EOF avant que l'appel d'impression ne soit émis.
comment lisez-vous de stdin en Python?
j'essaie de faire quelques-uns des défis de golf de code, mais ils exigent tous l'entrée à partir de stdin. Comment puis-je obtenir qu'en Python?
vous pouvez utiliser:
-
sys.stdin
- un objet semblable à un fichier-appelezsys.stdin.read()
pour tout lire. -
input(prompt)
- passer une invite optionnelle à la sortie, il lit de stdin jusqu'à la première ligne, qu'il bande. Vous devez le faire à plusieurs reprises pour obtenir plus de lignes, à la fin de l'input il soulève EOFError. (Probablement pas idéal pour jouer au golf.) En Python 2, c'estrawinput(prompt)
. -
open(0).read()
- en Python 3open
accepte descripteurs de fichiers (nombres entiers représentant le système d'exploitation IO ressources), et 0 est le descripteur destdin
. Il retourne un objet semblable à un fichier commesys.stdin
-probablement votre meilleure option pour le golf. -
open('/dev/stdin').read()
- similaire àopen(0)
, fonctionne sur Python 2 et 3, mais pas sur Windows (ou même Cygwin). -
fileinput.input()
- renvoie un itérateur sur des lignes dans tous les fichiers listés danssys.argv[1:]
, ou stdin si non indiqué. Utilisez comme''.join(fileinput.input())
.
les Deux sys
et fileinput
doivent être importés, respectivement, bien sûr.
Quick sys.stdin
exemples compatibles avec Python 2 et 3, Windows, Unix
vous avez juste besoin de read
de sys.stdin
, par exemple, si vous pipez des données à stdin:
$ echo foo | python -c "import sys; print(sys.stdin.read())"
foo
exemple de fichier
dites que vous avez un fichier, inputs.txt
, nous pouvons accepter ce fichier et le réécrire:
python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
plus longue réponse
voici une démo complète, facilement reproductible, utilisant deux méthodes, la fonction de compilation, input
(utilisez raw_input
en Python 2), et sys.stdin
. Les données ne sont pas modifiées, donc le traitement est une non-opération.
pour commencer, créons un fichier pour les entrées:
$ python -c "print('foo\nbar\nbaz')" > inputs.txt
Et en utilisant le code que nous avons déjà vu, nous pouvons vérifier que nous avons créé le dossier:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz
Voici l'aide sur sys.stdin.read
de 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.
fonction intégrée, input
( raw_input
en Python 2)
la fonction intégrée input
lit à partir de l'entrée standard jusqu'à une nouvelle ligne, qui est dépouillée (en complément de print
, qui ajoute une nouvelle ligne par défaut.) Ceci se produit jusqu'à ce qu'il obtienne EOF (fin du fichier), à quel point il soulève EOFError
.
ainsi, voici comment vous pouvez utiliser input
en Python 3 (ou raw_input
en Python 2) pour lire à partir de stdin - donc nous créons un module Python que nous appelons stdindemo.py:
$ python -c "print('try:\n while True:\n print(input())\nexcept EOFError:\n pass')" > stdindemo.py
et imprimons-le à l'envers pour nous assurer que c'est ce que nous attendons:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo.py
try:
while True:
print(input())
except EOFError:
pass
de nouveau, input
lit jusqu'à la nouvelle ligne et essentiellement le dépouille de la ligne. print
ajoute une nouvelle ligne. Donc pendant qu'ils modifient tous les deux l'entrée, leurs modifications annuler. (Elles sont donc essentiellement complémentaires les unes des autres.)
et quand input
obtient le caractère de fin de fichier, il élève EOFError, que nous ignorons et que nous sortons du programme.
et sur Linux / Unix, nous pouvons pipe de cat:
$ cat inputs.txt | python -m stdindemo
foo
bar
baz
ou nous pouvons simplement rediriger le fichier de stdin:
$ python -m stdindemo < inputs.txt
foo
bar
baz
nous pouvons également exécuter le module comme un script:
$ python stdindemo.py < inputs.txt
foo
bar
baz
Voici l'aide sur le builtin input
de Python 3:
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
ici nous faisons un script de démonstration en utilisant sys.stdin
. La façon efficace d'itérer un objet de type fichier est d'utiliser l'objet de type fichier comme un itérateur. La méthode complémentaire pour écrire à stdout à partir de cette entrée est d'utiliser simplement sys.stdout.write
:
$ python -c "print('import sys\nfor line in sys.stdin:\n sys.stdout.write(line)')" > stdindemo2.py
L'imprimer à l'envers pour s'assurer qu'il a l'air juste:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo2.py
import sys
for line in sys.stdin:
sys.stdout.write(line)
et redirection des entrées dans le fichier:
$ python -m stdindemo2 < inputs.txt
foo
bar
baz
ont joué au golf en une commande:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz
descripteurs de fichier pour le golf
puisque les descripteurs de fichier pour stdin
et stdout
sont 0 et 1 respectivement, nous pouvons aussi passer ceux à open
en Python 3 (Pas 2, et notez que nous avons toujours besoin du" w " pour écrire à stdout).
Si cela fonctionne sur votre système, il va raser plus de caractères.
$ python -c "open(1,'w').write(open(0).read())" < inputs.txt
baz
bar
foo
Python 2 io.open
le fait aussi, mais l'importation prend beaucoup plus d'espace:
$ python -c "from io import open; open(1,'w').write(open(0).read())" < inputs.txt
foo
bar
baz
pour répondre à d'autres commentaires et réponses
un commentaire suggère ''.join(sys.stdin)
mais c'est en fait plus long que sys.stdin.read () - plus Python doit créer une liste supplémentaire en mémoire (c'est comme ça que str.join
fonctionne lorsqu'il n'est pas donné liste) - pour Contraste:
''.join(sys.stdin)
sys.stdin.read()
La réponse sommet, suggère:
import fileinput
for line in fileinput.input():
pass
mais, puisque sys.stdin
implémente l'API de fichier, y compris le protocole iterator, c'est la même chose que ceci:
import sys
for line in sys.stdin:
pass
Autre réponse ne le suggérer. Il suffit de se rappeler que si vous le faites dans un interprète, vous aurez besoin de faire Ctrl - d si vous êtes sur Linux ou Mac, ou Ctrl - z sur Windows (après entrer ) pour envoyer le caractère de fin de fichier au processus. En outre, cette réponse suggère print(line)
- qui ajoute un '\n'
à l'utilisation finale print(line, end='')
à la place (si dans Python 2, vous aurez besoin de from __future__ import print_function
).
le véritable cas d'utilisation pour fileinput
est pour la lecture dans une série de fichiers.
cela fera écho entrée standard à sortie standard:
import sys
line = sys.stdin.readline()
while line:
print line,
line = sys.stdin.readline()
en S'appuyant sur tous les anwers en utilisant sys.stdin
, vous pouvez aussi faire quelque chose comme ce qui suit pour lire à partir d'un fichier d'argument si au moins un argument existe, et retomber à stdin autrement:
import sys
f = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin
for line in f:
# Do your stuff
et l'utiliser comme soit
$ python do-my-stuff.py infile.txt
ou
$ cat infile.txt | python do-my-stuff.py
ou même
$ python do-my-stuff.py < infile.txt
qui ferait en sorte que votre script Python se comporte comme beaucoup de programmes GNU/Unix tels que cat
, grep
et sed
.
la puce de code suivante vous aidera (elle lira tout le blocage de stdin jusqu'à EOF
, dans une chaîne de caractères):
import sys
input_str = sys.stdin.read()
print input_str.split()
vous pouvez lire à partir de stdin et ensuite stocker les entrées dans "données comme suit:
data = ""
for line in sys.stdin:
data += line
essayez ceci:
import sys
print sys.stdin.read().upper()
et vérifiez avec:
$ echo "Hello World" | python myFile.py
je suis assez étonné que personne n'ait mentionné ce piratage jusqu'à présent:
python -c "import sys;print (''.join([l for l in sys.stdin.readlines()]))"
compatible avec python2 et python3
lire de sys.stdin
, mais à lire les données binaires sur Windows , vous devez être très prudent, parce que sys.stdin
il est ouvert en mode texte et il sera corrompu \r\n
les remplacer par \n
.
la solution est de définir le mode binaire si Windows + Python 2 est détecté, et sur Python 3 utiliser sys.stdin.buffer
.
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()
le problème que j'ai avec la solution
import sys
for line in sys.stdin:
print(line)
est que si vous ne passez pas de données à stdin, il va bloquer pour toujours. C'est pourquoi j'adore cette réponse : Vérifiez s'il y a des données sur stdin d'abord, puis lisez-les. C'est ce que j'ai fini par faire:
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)
j'ai eu quelques problèmes quand obtenir ce travail pour la lecture sur les douilles raccordées à elle. Lorsque la prise s'est fermée, elle a commencé à renvoyer une chaîne vide dans une boucle active. Donc c'est ma solution (que j'ai seulement testé sous linux, mais j'espère qu'elle fonctionne sur tous les autres systèmes)
import sys, os
sep=os.linesep
while sep == os.linesep:
data = sys.stdin.readline()
sep = data[-len(os.linesep):]
print '> "%s"' % data.strip()
donc si vous commencez à écouter sur une socket, cela fonctionnera correctement (par exemple en bash):
while :; do nc -l 12345 | python test.py ; done
Et vous pouvez l'appeler avec telnet ou tout simplement pointer un navigateur lieu: 12345
à propos de ceci:
for line in sys.stdin:
je viens de l'essayer sur python 2.7 (suivant la suggestion de quelqu'un d'autre) pour un très gros fichier, et je ne le recommande pas, précisément pour les raisons mentionnées ci-dessus (rien n'arrive pendant longtemps).
j'ai fini avec une solution un peu plus pythonique (et cela fonctionne sur des fichiers plus gros):
with open(sys.argv[1], 'r') as f:
for line in f:
alors je peux exécuter le script localement comme:
python myscript.py "0 1 2 3 4..." # can be a multi-line string or filename - any std.in input will work
n = int(raw_input())
for i in xrange(n):
name, number = raw_input().split()
en complément de ces réponses, vous pouvez également utiliser argparse
qui est également rétrocompatible avec python2.7 . Exemple compatible à la fois python2 et python3:
#!/usr/bin/python
import argparse
import sys
parser = argparse.ArgumentParser()
parser.add_argument('in', default=sys.stdin, type=argparse.FileType('r'), nargs='?')
args = parser.parse_args()
data = args.in.read()
Vous pouvez exécuter ce script de deux façons:
-
utilisant
stdin
:echo 'foo bar' | ./above-script.py
-
utilisant un argument de nom de fichier:
echo 'foo bar' > text-file ./above-script.py text-file