¿Cómo lees desde stdin?

Estoy tratando de hacer algunos de los desafíos del código de golf , pero todos requieren la entrada de stdin . ¿Cómo consigo eso en Python?

Podrías usar el módulo fileinput :

 import fileinput for line in fileinput.input(): pass 

fileinput recorrerá todas las líneas en la entrada especificada como nombres de archivo en los argumentos de la línea de comandos, o la entrada estándar si no se proporcionan argumentos.

Nota: la line contendrá una nueva línea final; para eliminarlo use line.rstrip()

Hay algunas maneras de hacerlo.

  • sys.stdin es un objeto similar a un archivo en el que puede llamar a las funciones read o read readlines si desea leer todo o si quiere leer todo y dividirlo por nueva línea automáticamente. (Necesitas import sys para que esto funcione.)

  • Si desea solicitar información al usuario, puede usar raw_input en Python 2.X, y solo input en Python 3.

  • Si solo quiere leer las opciones de la línea de comandos, puede acceder a ellas a través de la lista sys.argv .

Probablemente encuentre que este artículo de Wikilibros sobre E / S en Python también es una referencia útil.

 import sys for line in sys.stdin: print line 

Python también tiene funciones incorporadas input() y raw_input() . Consulte la documentación de Python en Funciones integradas .

Por ejemplo,

 name = raw_input("Enter your name: ") # Python 2.x 

o

 name = input("Enter your name: ") # Python 3 

Aquí está de aprender Python :

 import sys data = sys.stdin.readlines() print "Counted", len(data), "lines." 

En Unix, puedes probarlo haciendo algo como:

 % cat countlines.py | python countlines.py Counted 3 lines. 

En Windows o DOS, harías:

 C:\> type countlines.py | python countlines.py Counted 3 lines. 

La respuesta propuesta por otros:

 for line in sys.stdin: print line 

Es muy simple y pythonic, pero debe tenerse en cuenta que el script esperará hasta EOF antes de comenzar a iterar en las líneas de entrada.

Esto significa que tail -f error_log | myscript.py tail -f error_log | myscript.py no procesará las líneas como se esperaba.

El script correcto para tal caso de uso sería:

 while 1: try: line = sys.stdin.readline() except KeyboardInterrupt: break if not line: break print line 

ACTUALIZAR
De los comentarios, se ha aclarado que solo en Python 2 podría haber un búfer involucrado, por lo que terminará esperando que se llene el búfer o EOF antes de que se emita la llamada de impresión.

¿Cómo lees desde stdin en Python?

Estoy tratando de hacer algunos de los desafíos del código de golf, pero todos requieren la entrada de stdin. ¿Cómo consigo eso en Python?

Puedes usar:

  • sys.stdin : un objeto similar a un archivo: llame a sys.stdin.read() para leer todo.
  • input(prompt) : pásele un prompt opcional a la salida, lee desde la entrada estándar hasta la primera línea nueva, que elimina. Tendrías que hacer esto repetidamente para obtener más líneas, al final de la entrada se genera EOFError. (Probablemente no sea bueno para jugar al golf). En Python 2, esto es rawinput(prompt) .
  • open(0).read() : en Python 3 open acepta descriptores de archivos (enteros que representan los recursos de E / S del sistema operativo), y 0 es el descriptor de stdin . Devuelve un objeto similar a un archivo como sys.stdin , probablemente su mejor apuesta para jugar al golf.
  • open('/dev/stdin').read() – similar a open(0) , funciona en Python 2 y 3, pero no en Windows (o incluso Cygwin).
  • fileinput.input() : devuelve un iterador sobre las líneas en todos los archivos enumerados en sys.argv[1:] , o stdin si no se proporciona. Use como ''.join(fileinput.input()) .

Tanto sys como fileinput deben ser importados, respectivamente, por supuesto.

Ejemplos de sys.stdin rápidos compatibles con Python 2 y 3, Windows, Unix

Solo necesita read desde sys.stdin , por ejemplo, si canaliza datos a stdin:

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

ejemplo de archivo

Digamos que tiene un archivo, inputs.txt , podemos aceptar ese archivo y volver a escribirlo:

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

Respuesta más larga

Aquí hay una demostración completa, fácilmente replicable, que utiliza dos métodos, la función incorporada, input (use raw_input en Python 2) y sys.stdin . Los datos no están modificados, por lo que el procesamiento no es una operación.

Para empezar, vamos a crear un archivo para las entradas:

 $ python -c "print('foo\nbar\nbaz')" > inputs.txt 

Y utilizando el código que ya hemos visto, podemos verificar que hemos creado el archivo:

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

Aquí está la ayuda en 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. 

Función incorporada, input ( raw_input en Python 2)

La input función incorporada lee desde la entrada estándar hasta una nueva línea, que se elimina (complementando la print , que agrega una nueva línea de forma predeterminada). Esto ocurre hasta que obtiene EOF (Fin del archivo), momento en el que genera EOFError .

Por lo tanto, aquí es cómo puede usar la input en Python 3 (o raw_input en Python 2) para leer desde stdin, así que creamos un módulo de Python que llamamos stdindemo.py:

 $ python -c "print('try:\n while True:\n print(input())\nexcept EOFError:\n pass')" > stdindemo.py 

Y vamos a imprimirlo de nuevo para asegurarnos de que sea como esperamos:

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

De nuevo, la input lee hasta la nueva línea y, esencialmente, la elimina de la línea. print añade una nueva línea. Así que mientras ambos modifican la entrada, sus modificaciones se cancelan. (Así que son esencialmente el complemento de cada uno.)

Y cuando la input obtiene el carácter de fin de archivo, genera EOFError, que ignoramos y luego salimos del progtwig.

Y en Linux / Unix, podemos canalizar desde cat:

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

O simplemente podemos redirigir el archivo desde la entrada estándar:

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

También podemos ejecutar el módulo como un script:

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

Aquí está la ayuda en la input incorporada 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

Aquí hacemos un script de demostración utilizando sys.stdin . La manera eficiente de iterar sobre un objeto similar a un archivo es usar el objeto similar a un archivo como un iterador. El método complementario para escribir en stdout desde esta entrada es simplemente usar sys.stdout.write :

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

Imprímelo de nuevo para asegurarse de que se vea bien:

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

Y redireccionando las entradas al archivo:

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

Jugó en un comando:

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

Descriptores de archivo para el golf

Dado que los descriptores de archivo para stdin y stdout son 0 y 1 respectivamente, también podemos pasarlos para open en Python 3 (no 2, y tenga en cuenta que todavía necesitamos la 'w' para escribir en stdout).

Si esto funciona en su sistema, eliminará más caracteres.

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

El io.open Python 2 io.open hace esto, pero la importación ocupa mucho más espacio:

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

Abordar otros comentarios y respuestas.

Un comentario sugiere ''.join(sys.stdin) pero en realidad es más largo que sys.stdin.read (); además, Python debe crear una lista adicional en la memoria (así es como funciona str.join cuando no se le da una lista) - para el contraste :

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

La respuesta superior sugiere:

 import fileinput for line in fileinput.input(): pass 

Pero, dado que sys.stdin implementa la API del archivo, incluido el protocolo del iterador, es lo mismo que esto:

 import sys for line in sys.stdin: pass 

Otra respuesta sugiere esto. Solo recuerde que si lo hace en un intérprete, deberá hacer Ctrl - d si está en Linux o Mac, o Ctrl - z en Windows (después de Enter ) para enviar el carácter de final de archivo a la proceso. Además, esa respuesta sugiere print(line) - que agrega un '\n' al final - use print(line, end='') lugar (si está en Python 2, necesitará from __future__ import print_function ).

El verdadero caso de uso para la fileinput de fileinput es para leer en una serie de archivos.

Esto hará eco de la entrada estándar a la salida estándar:

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

Sobre la base de todas las respuestas que utilizan sys.stdin , también puede hacer algo como lo siguiente para leer un archivo de argumentos si existe al menos un argumento, y, de lo contrario, volver a stdin:

 import sys f = open(sys.argv[1]) if len(sys.argv) > 1 else sys.stdin for line in f: # Do your stuff 

y usarlo como cualquiera

 $ python do-my-stuff.py infile.txt 

o

 $ cat infile.txt | python do-my-stuff.py 

o incluso

 $ python do-my-stuff.py < infile.txt 

Eso haría que su script de Python se comportara como muchos progtwigs GNU / Unix como cat , grep y sed .

El siguiente chip de código te ayudará (leerá todos los lockings estándar hasta EOF , en una cadena):

 import sys input_str = sys.stdin.read() print input_str.split() 

argparse es una solución fácil

Ejemplo compatible con ambas versiones de Python 2 y 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() 

Puede ejecutar este script de muchas maneras:

1. Usando stdin

 echo 'foo bar' | ./above-script.py 

o más corto reemplazando el echo por la cadena aquí :

 ./above-script.py <<< 'foo bar' 

2. Usando un argumento de nombre de archivo

 echo 'foo bar' > my-file.data ./above-script.py my-file.data 

3. Usando stdin través del nombre de archivo especial -

 echo 'foo bar' | ./above-script.py - 

Prueba esto:

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

y comprobarlo con:

 $ echo "Hello World" | python myFile.py 

Puede leer desde la entrada estándar y luego almacenar las entradas en “datos” de la siguiente manera:

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

Estoy bastante sorprendido de que nadie haya mencionado este hack hasta ahora:

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

compatible con python2 y python3

Lea desde sys.stdin , pero para leer datos binarios en Windows , debe tener mucho cuidado, porque sys.stdin se abre en modo de texto y se sys.stdin \r\n reemplazándolos con \n .

La solución es configurar el modo en binario si se detecta Windows + Python 2, y en Python 3 use 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() 

El problema que tengo con la solución.

 import sys for line in sys.stdin: print(line) 

es que si no pasas ningún dato a stdin, se bloqueará para siempre. Por eso me encanta esta respuesta : compruebe si hay algún dato en stdin primero y luego léalo. Esto es lo que terminé haciendo:

 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) 

Tuve algunos problemas al hacer que esto funcionara para la lectura a través de sockets conectados a él. Cuando el socket se cerró, comenzó a devolver una cadena vacía en un bucle activo. Así que esta es mi solución (que solo probé en Linux, pero espero que funcione en todos los demás sistemas)

 import sys, os sep=os.linesep while sep == os.linesep: data = sys.stdin.readline() sep = data[-len(os.linesep):] print '> "%s"' % data.strip() 

Entonces, si empiezas a escuchar en un socket funcionará correctamente (por ejemplo, en bash):

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

Y puede llamarlo con telnet o simplemente apuntar un navegador a localhost: 12345

Con respecto a este:

for line in sys.stdin:

Lo probé en Python 2.7 (siguiendo la sugerencia de otra persona) para un archivo muy grande, y no lo recomiendo, precisamente por las razones mencionadas anteriormente (no pasa nada durante mucho tiempo).

Terminé con una solución un poco más pythonic (y funciona en archivos más grandes):

 with open(sys.argv[1], 'r') as f: for line in f: 

Entonces puedo ejecutar el script localmente como:

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