¿Cómo se lee de stdin en Python?
Estoy tratando de hacer algunos de los desafíos de código de golf, pero todos requieren que la entrada se tome de stdin. ¿Cómo consigo eso en Python?
Puedes usar:
sys.stdin
– Un objeto similar a un archivo – llamarsys.stdin.read()
para leer todo.input(prompt)
– pasarle un mensaje opcional a la salida, lee desde stdin hasta la primera línea nueva, que elimina. Tendría que hacer esto repetidamente para obtener más líneas, al final de la entrada genera EOFError. (Probablemente no sea bueno para jugar al golf). En Python 2, esto esrawinput(prompt)
.open(0).read()
– En Python 3, la función incorporadaopen
acepta descriptores de archivo (números enteros que representan los recursos de E / S del sistema operativo) y 0 es el descriptor destdin
. Devuelve un objeto similar a un archivo comosys.stdin
– probablemente su mejor apuesta para jugar al golf. En Python 2, esto esio.open
.open('/dev/stdin').read()
– Similar aopen(0)
, funciona en Python 2 y 3, pero no en Windows (ni siquiera en Cygwin).fileinput.input()
– devuelve un iterador sobre las líneas en todos los archivos enumerados ensys.argv[1:]
, o stdin si no se administra. Usar como''.join(fileinput.input())
.
Ambos sys
y fileinput
deben ser importados, respectivamente, por supuesto.
Rápido sys.stdin
ejemplos compatibles con Python 2 y 3, Windows, Unix
Solo necesitas read
de sys.stdin
, por ejemplo, si canaliza datos a stdin:
$ echo foo | python -c "import sys; print(sys.stdin.read())"
foo
Podemos ver eso sys.stdin
está en modo de texto predeterminado:
>>> import sys
>>> sys.stdin
<_io.TextIOWrapper name="<stdin>" mode="r" encoding='UTF-8'>
ejemplo de archivo
Digamos que tienes 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, usando dos métodos, la función incorporada, input
(usar raw_input
en Python 2), y sys.stdin
. Los datos no se modifican, por lo que el procesamiento es una no operación.
Para empezar, creemos un archivo para las entradas:
$ python -c "print('foonbarnbaz')" > inputs.txt
Y usando 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 sobre sys.stdin.read
desde 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 función incorporada input
lee desde la entrada estándar hasta una nueva línea, que se elimina (complementando print
, que agrega una nueva línea de forma predeterminada). Esto ocurre hasta que obtiene EOF (Fin de archivo), momento en el que aumenta EOFError
.
Por lo tanto, así es como puede usar input
en Python 3 (o raw_input
en Python 2) para leer desde stdin, por lo 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
E imprimámoslo 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, input
lee hasta el salto de línea y esencialmente lo quita de la línea. print
agrega una nueva línea. Entonces, mientras ambos modifican la entrada, sus modificaciones se cancelan. (Entonces, son esencialmente el complemento de cada uno).
Y cuando 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 stdin:
$ python -m stdindemo < inputs.txt
foo
bar
baz
También podemos ejecutar el módulo como script:
$ python stdindemo.py < inputs.txt
foo
bar
baz
Aquí está la ayuda en el builtin input
desde 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 usando sys.stdin
. La forma 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 sysnfor line in sys.stdin:n sys.stdout.write(line)')" > stdindemo2.py
Vuelva a imprimirlo 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 redirigiendo las entradas al archivo:
$ python -m stdindemo2 < inputs.txt
foo
bar
baz
Golf en un comando:
$ python -c "import sys; sys.stdout.write(sys.stdin.read())" < inputs.txt
foo
bar
baz
Descriptores de archivo para golf
Dado que los descriptores de archivo para stdin
y stdout
son 0 y 1 respectivamente, también podemos pasarlos a 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
Python 2 io.open
también 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)
para jugar al golf, 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 str.join
funciona cuando no se le da una lista) – para contraste:
''.join(sys.stdin)
sys.stdin.read()
La respuesta principal sugiere:
import fileinput
for line in fileinput.input():
pass
Pero desde sys.stdin
implementa la API de archivos, incluido el protocolo de iterador, que es lo mismo que esto:
import sys
for line in sys.stdin:
pass
Otra respuesta lo hace sugiero esto. Solo recuerde que si lo hace en un intérprete, deberá hacerlo control–D si está en Linux o Mac, o control–z en Windows (después Ingresar) para enviar el carácter de fin de archivo al proceso. Además, esa respuesta sugiere print(line)
– que agrega un 'n'
hasta el final – uso print(line, end='')
en su lugar (si está en Python 2, necesitará from __future__ import print_function
).
El caso de uso real para fileinput
es para leer en una serie de archivos.