Pregunta ¿Cómo se lee desde stdin en Python?


Estoy tratando de hacer algunas de las código de golf desafíos, pero todos requieren que se tome la información de stdin. ¿Cómo lo obtengo en Python?


1171
2017-09-20 05:48


origen


Respuestas:


Podrías usar el fileinput módulo:

import fileinput

for line in fileinput.input():
    pass

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


801
2017-09-20 05:53



Hay algunas maneras de hacerlo.

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

  • Si quieres rápido el usuario para la entrada, puede usar raw_input en Python 2.X, y solo input en Python 3.

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

Probablemente encontrarás este artículo de Wikibook sobre E / S en Python para ser una referencia útil también.


584
2017-07-20 10:30



import sys

for line in sys.stdin:
    print line

331
2018-03-03 19:05



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

Por ejemplo,

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

o

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

180
2017-09-30 09:08



Aquí está de Aprendiendo 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.

160
2017-07-30 04:10



La respuesta propuesta por otros:

for line in sys.stdin:
  print line

es muy simple y pitónico, 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 no procesará las líneas como se esperaba.

La secuencia de comandos correcta para dicho 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 en python 2 solo puede haber memoria intermedia involucrada, por lo que terminas esperando que el buffer se complete o EOF antes de que se emita la llamada de impresión.


85
2017-08-09 16:31



¿Cómo se lee desde stdin en Python?

Estoy tratando de hacer algunos de los desafíos de golf de código, pero todos requieren que la entrada se tome de stdin. ¿Cómo lo obtengo en Python?

Puedes usar:

  • sys.stdin - Un objeto similar a un archivo - llamada sys.stdin.read() para leer todo
  • input(prompt) - pasarle un mensaje opcional para dar salida, se lee desde stdin hasta la primera nueva línea, que se elimina. Tendría que hacer esto repetidamente para obtener más líneas, al final de la entrada se genera EOFError. (Probablemente no sea genial 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 IO 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 líneas en todos los archivos listados en sys.argv[1:], o stdin si no se da. Usa como ''.join(fileinput.input()).

Ambos sys y fileinput debe ser importado, 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 canalizas datos a stdin:

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

ejemplo de archivo

Digamos que tienes un archivo inputs.txt, podemos aceptar ese archivo y escribirlo de nuevo:

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

Respuesta más larga

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

Para empezar, creemos un archivo para las entradas:

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

Y usando el código que ya hemos visto, podemos verificar que hayamos 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 función integrada input lee desde la entrada estándar hasta una nueva línea, que se elimina (complementando print, lo que agrega una nueva línea por defecto.) Esto ocurre hasta que obtiene EOF (Fin del archivo), en cuyo punto aumenta EOFError.

Por lo tanto, así es cómo puedes usar input en Python 3 (o raw_input en Python 2) para leer de stdin, entonces 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 imprimámoslo de nuevo para garantizar 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 la nueva línea y esencialmente la 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 un script:

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

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

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 sys\nfor line in sys.stdin:\n    sys.stdout.write(line)')" > stdindemo2.py

Imprima 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

Golfed en un comando:

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

Descriptores de archivos para jugar al golf

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

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

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

Python 2's io.open hace esto también, pero la importación requiere 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 de que Python debe crear una lista extra en la memoria (así es como str.join funciona cuando no se le da una lista) - por contraste:

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

La respuesta superior sugiere:

import fileinput

for line in fileinput.input():
    pass

Pero desde sys.stdin implementa el archivo API, incluido el protocolo de iterador, que es el mismo que este:

import sys

for line in sys.stdin:
    pass

Otra respuesta hace sugerir esto Solo recuerde que si lo hace en un intérprete, tendrá que hacer Ctrl-re si estás en Linux o Mac, o Ctrl-z en Windows (después Entrar) 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 - use print(line, end='') en cambio (si está en Python 2, necesitará from __future__ import print_function)

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


49
2017-07-29 15:04



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

36
2018-01-25 10:26



Construyendo sobre todas las torres usando sys.stdin, también puede hacer algo como lo siguiente para leer desde un archivo de argumento si existe al menos un argumento, y recurrir a stdin de lo contrario:

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

$ 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 tu script Python se comportara como muchos programas GNU / Unix, como cat, grep y sed.


28
2017-08-27 15:43



El siguiente chip de código te ayudará (leerá todo el bloqueo de stdin en EOF, en una cadena):

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

12
2017-07-20 21:33