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 asys.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 3open
acepta descriptores de archivos (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. -
open(''/dev/stdin'').read()
- similar aopen(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 ensys.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 funcionesread
oread
readlines
si desea leer todo o si quiere leer todo y dividirlo por nueva línea automáticamente. (Necesitasimport sys
para que esto funcione.)Si desea solicitar información al usuario, puede usar
raw_input
en Python 2.X, y soloinput
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()
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()