read - sys.stdin python




Comment lisez-vous depuis stdin en Python? (13)

Comment lisez-vous depuis stdin en Python?

J'essaie de faire quelques-uns des défis de golf de code, mais ils exigent tous l'entrée à prendre de stdin. Comment puis-je obtenir cela en Python?

Vous pouvez utiliser:

  • sys.stdin - Un objet semblable à un fichier - appelle sys.stdin.read() pour tout lire.
  • input(prompt) - passez-lui une invite facultative à la sortie, il lit à partir de stdin jusqu'à la première ligne, qu'il supprime. Vous auriez à le faire à plusieurs reprises pour obtenir plus de lignes, à la fin de l'entrée, il soulève EOFError. (Probablement pas génial pour le golf.) Dans Python 2, c'est rawinput(prompt) .
  • open(0).read() - En Python 3 open accepte les descripteurs de fichier (entiers représentant les ressources d'E / S du système d'exploitation), et 0 est le descripteur de stdin . Il renvoie un objet semblable à un fichier comme sys.stdin - probablement votre meilleur pari 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() - retourne un itérateur sur toutes les lignes de tous les fichiers listés dans sys.argv[1:] , ou stdin s'il n'est pas sys.argv[1:] . Utilisez comme ''.join(fileinput.input()) .

Les deux sys et fileinput doivent être importés, respectivement, bien sûr.

Exemples sys.stdin rapides compatibles avec Python 2 et 3, Windows, Unix

Vous avez juste besoin de read depuis sys.stdin , par exemple, si vous sys.stdin données vers stdin:

$ echo foo | python -c "import sys; print(sys.stdin.read())"
foo

exemple de fichier

Disons que vous avez un fichier, inputs.txt , nous pouvons accepter ce fichier et l'écrire à nouveau:

python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt

Réponse plus longue

Voici une démo complète, facilement reproductible, utilisant deux méthodes, la fonction intégrée, input (utiliser raw_input dans 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 fichier:

$ 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 dans Python 2)

L' input fonction intégrée lit l'entrée standard jusqu'à une nouvelle ligne, qui est supprimée (en complétant print , qui ajoute une nouvelle ligne par défaut). Cela se produit jusqu'à ce qu'elle obtienne EOF (End Of File), à ​​quel point elle soulève EOFError .

Ainsi, voici comment vous pouvez utiliser l' input dans Python 3 (ou raw_input dans Python 2) pour lire depuis 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 pour nous assurer que c'est comme nous l'espérons:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo.py 
try:
    while True:
        print(input())
except EOFError:
    pass

Encore une fois, l' input lit jusqu'à la nouvelle ligne et la supprime essentiellement de la ligne. print ajoute une nouvelle ligne. Ainsi, pendant qu'ils modifient l'entrée, leurs modifications s'annulent. (Donc, ils sont essentiellement le complément de l'autre.)

Et lorsque l' input reçoit le caractère de fin de fichier, elle déclenche EOFError, que nous ignorons puis quitte le programme.

Et sur Linux / Unix, on peut passer du chat:

$ cat inputs.txt | python -m stdindemo
foo
bar
baz

Ou nous pouvons simplement rediriger le fichier à partir de stdin:

$ python -m stdindemo < inputs.txt 
foo
bar
baz

Nous pouvons également exécuter le module en tant que script:

$ python stdindemo.py < inputs.txt 
foo
bar
baz

Voici l'aide sur l' input intégrée 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émo en utilisant sys.stdin . Le moyen efficace d'itérer sur un objet semblable à un fichier consiste à utiliser l'objet semblable à un fichier en tant qu'itérateur. La méthode complémentaire pour écrire sur stdout à partir de cette entrée consiste simplement à utiliser sys.stdout.write :

$ python -c "print('import sys\nfor line in sys.stdin:\n    sys.stdout.write(line)')" > stdindemo2.py

Imprimez-le pour vous assurer qu'il a l'air correct:

$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < stdindemo2.py 
import sys
for line in sys.stdin:
    sys.stdout.write(line)

Et rediriger les entrées dans le fichier:

$ python -m stdindemo2 < inputs.txt
foo
bar
baz

Golfé dans 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 fichiers pour stdin et stdout sont respectivement 0 et 1, nous pouvons également passer ceux-ci à open dans Python 3 (pas 2, et notez que nous avons toujours besoin du 'w' pour écrire sur 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

Le io.open Python 2 le fait également, mais l'importation prend beaucoup plus de place:

$ python -c "from io import open; open(1,'w').write(open(0).read())" < inputs.txt 
foo
bar
baz

Adresser 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 str.join que str.join fonctionne quand on ne lui donne pas de liste) - pour le contraste :

''.join(sys.stdin)
sys.stdin.read()

La meilleure réponse suggère:

import fileinput

for line in fileinput.input():
    pass

Mais, puisque sys.stdin implémente l'API de fichier, y compris le protocole d'itérateur, c'est exactement la même chose:

import sys

for line in sys.stdin:
    pass

Une autre réponse suggère cela. Rappelez-vous simplement que si vous le faites dans un interpréteur, vous devrez faire Ctrl - d si vous êtes sous Linux ou Mac, ou Ctrl - z sous Windows (après Entrée ) pour envoyer le caractère de fin de fichier à l'interpréteur. processus. Aussi, cette réponse suggère print(line) - qui ajoute un '\n' à la fin - use print(line, end='') place (si dans Python 2, vous aurez besoin from __future__ import print_function ).

Le vrai cas d' fileinput de fileinput est de lire dans une série de fichiers.

J'essaie de faire quelques-uns des défis de golf de code , mais ils exigent tous l'entrée à prendre de stdin . Comment puis-je obtenir cela en Python?


Cela fera écho à l'entrée standard à la sortie standard:

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

En se basant sur toutes les réponses à l'aide de sys.stdin , vous pouvez également faire quelque chose comme ce qui suit pour lire un fichier d'argument si au moins un argument existe, et revenir à stdin sinon:

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

$ 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

Cela ferait que votre script Python se comporte comme de nombreux programmes GNU / Unix tels que cat , grep et sed .


Essaye ça:

import sys

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

et vérifiez avec:

$ echo "Hello World" | python myFile.py

J'ai eu quelques problèmes lors de l'obtention de ce travail pour lire sur les sockets piped à elle. Lorsque le socket s'est fermé, il a commencé à retourner une chaîne vide dans une boucle active. Donc, voici ma solution (que j'ai seulement testée sous Linux, mais j'espère que cela fonctionne dans 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 dans bash):

while :; do nc -l 12345 | python test.py ; done

Et vous pouvez l'appeler avec telnet ou simplement pointer un navigateur vers localhost: 12345


Je suis assez étonné que personne n'ait mentionné ce hack jusqu'à maintenant:

python -c "import sys;print (''.join([l for l in sys.stdin.readlines()]))"

compatible avec python2 et python3


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

METTRE À JOUR
Des commentaires il a été effacé que sur Python 2 seulement il pourrait y avoir un tampon impliqué, de sorte que vous finissiez par attendre que le tampon remplisse ou EOF avant que l'appel d'impression soit émis.


Le problème que j'ai avec la solution

import sys

for line in sys.stdin:
    print(line)

est que si vous ne transmettez pas de données à stdin, il bloquera pour toujours. C'est pourquoi j'aime cette réponse : vérifiez s'il y a d'abord des données sur stdin, 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)

Python a aussi des fonctions intégrées 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

Une option consiste à utiliser la fonction d'entrée comme indiqué ci-dessous. Il y a aussi la méthode raw_input si vous n'êtes pas sûr du type de données.

#!/usr/bin/env python

number = input("Please enter a number : ")
print("Entered number is %d" % number)

Exécuter le programme:

python test1.py

Please enter a number : 55
Entered number is 55

Référence: http://www.python-course.eu/input.php


Vous pouvez lire depuis stdin puis stocker les entrées dans "data" comme suit:

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

Vous pouvez utiliser le module fileinput :

import fileinput

for line in fileinput.input():
    pass

fileinput parcourt toutes les lignes de l'entrée spécifiées en tant que noms de fichiers donnés dans les arguments de la ligne de commande, ou l'entrée standard si aucun argument n'est fourni.


n = int(raw_input())
for i in xrange(n):
    name, number = raw_input().split()




stdin