read from español error python stdin

from - ¿Cómo lees desde stdin en Python?



stdout python (19)

¿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 : pásele un prompt opcional a la salida, lee desde la entrada estándar hasta la primera nueva línea, 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 listados 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 manera predeterminada). Esto ocurre hasta que obtiene EOF (Fin del archivo), momento en el que genera EOFError .

Por lo tanto, aquí le raw_input 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

Una vez más, 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 programa.

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ó al golf 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 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.

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?


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.


Como complemento de estas respuestas, también puede usar argparse que también es compatible con python2.7 . Ejemplo compatible tanto con python2 como con 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()

Puede ejecutar este script de dos maneras:

  • Utilizando stdin :

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

  • Usando un argumento de nombre de archivo:

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


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


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)


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

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


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


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


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


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.


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


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 comando, o la entrada estándar si no se proporcionan argumentos.


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


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


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 programas GNU / Unix como cat , grep y sed .


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


import sys for line in sys.stdin: print line


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