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?

1208
demandé sur Aaron Hall 2009-09-20 09:48:07

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.

823
répondu u0b34a0f6ae 2015-08-31 17:34:21

il y a plusieurs façons de le faire.

  • sys.stdin est un objet semblable à un fichier sur lequel vous pouvez appeler les fonctions read ou readlines si vous voulez tout lire ou vous voulez tout lire et le diviser par newline automatiquement. (Vous devez import 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 juste input 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.

602
répondu Mark Rushakoff 2018-06-27 20:21:59
import sys

for line in sys.stdin:
    print line
342
répondu user303110 2010-07-20 10:35:53

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
188
répondu Pat Notz 2017-09-11 18:47:00

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.
165
répondu Eugene Yokota 2017-12-10 19:22:29

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.

87
répondu Massimiliano Torromeo 2013-12-12 10:33:01

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-appelez sys.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'est rawinput(prompt) .
  • open(0).read() - en Python 3 open accepte descripteurs de fichiers (nombres entiers représentant le système d'exploitation IO ressources), et 0 est le descripteur de stdin . Il retourne un objet semblable à un fichier comme sys.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 dans sys.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.

56
répondu Aaron Hall 2018-04-10 21:01:15

cela fera écho entrée standard à sortie standard:

import sys
line = sys.stdin.readline()
while line:
    print line,
    line = sys.stdin.readline()
36
répondu rlib 2012-12-24 06:18:36

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 .

29
répondu Emil Lundberg 2015-08-24 12:53:25

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()
13
répondu Chandan Kumar 2018-02-02 20:01:02

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
8
répondu Wei 2015-02-26 10:52:10

essayez ceci:

import sys

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

et vérifiez avec:

$ echo "Hello World" | python myFile.py
7
répondu Boubakr 2013-08-27 15:43:43

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

6
répondu Uri Goren 2016-11-07 10:15:59

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()
4
répondu anatoly techtonik 2016-08-14 05:12:41

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)
4
répondu SummerBreeze 2017-11-02 08:49:46

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

2
répondu estani 2014-10-29 14:57:06

à 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
1
répondu szeitlin 2016-09-17 09:35:29
n = int(raw_input())
for i in xrange(n):
    name, number = raw_input().split()
0
répondu issam 2018-03-29 05:37:38

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
    
0
répondu olibre 2018-09-27 13:40:34