Estoy tratando de hacer algunos de los desafíos del código de golf , pero todos requieren que se tome la entrada stdin
. ¿Cómo consigo eso en Python?
1474
Estoy tratando de hacer algunos de los desafíos del código de golf , pero todos requieren que se tome la entrada stdin
. ¿Cómo consigo eso en Python?
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 comandos, o la entrada estándar si no se proporcionan argumentos.
Nota: line
contendrá una nueva línea final; para eliminarlo useline.rstrip()
Hay algunas formas de hacerlo.
sys.stdin
es un objeto similar a un archivo en el que puede llamar funcionesread
oreadlines
si desea leer todo o si desea leer todo y dividirlo por nueva línea automáticamente. (Es necesario queimport sys
esto funcione).Si desea solicitar al usuario una entrada, puede usarla
raw_input
en Python 2.X y soloinput
en Python 3.Si en realidad solo desea leer las opciones de la línea de comandos, puede acceder a ellas a través de la lista sys.argv .
Probablemente encontrará que este artículo de Wikibook sobre E / S en Python también es una referencia útil.
fuente
Tenga en cuenta que esto incluirá un carácter de nueva línea al final. Para eliminar la nueva línea al final, use
line.rstrip()
como dijo @brittohalloran.fuente
\r\n
los finales de líneaPython también tiene funciones integradas
input()
yraw_input()
. Consulte la documentación de Python en Funciones incorporadas .Por ejemplo,
o
fuente
Aquí está de Learning Python :
En Unix, puede probarlo haciendo algo como:
En Windows o DOS, harías:
fuente
print(sum(chunk.count('\n') for chunk in iter(partial(sys.stdin.read, 1 << 15), '')))
. verwc-l.py
cat
aquí es redundante. La invocación correcta para sistemas Unix espython countlines.py < countlines.py
.readlines()
. Los objetos de archivo están destinados a ser iterados sin materializar todos los datos en la memoria.Puedes usar:
sys.stdin
- Un objeto similar a un archivo: llamesys.stdin.read()
para leer todo.input(prompt)
- pásele un mensaje opcional para generar, 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 aumenta EOFError. (Probablemente no es genial para jugar al golf.) En Python 2, esto esrawinput(prompt)
.open(0).read()
- En Python 3, la función incorporadaopen
acepta descriptores de archivo (enteros que representan recursos de E / S del sistema operativo) y 0 es el descriptor destdin
. Devuelve un objeto similar a un archivosys.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 (o incluso Cygwin).fileinput.input()
- devuelve un iterador sobre líneas en todos los archivos enumeradossys.argv[1:]
, o stdin si no se proporciona. Utilizar como''.join(fileinput.input())
.Ambos
sys
yfileinput
deben importarse, respectivamente, por supuesto.sys.stdin
Ejemplos rápidos compatibles con Python 2 y 3, Windows, UnixSólo tiene que
read
partirsys.stdin
, por ejemplo, si los datos de tubería a la entrada estándar:Podemos ver que
sys.stdin
está en modo de texto predeterminado:ejemplo de archivo
Digamos que tiene un archivo,
inputs.txt
podemos aceptar ese archivo y volver a escribirlo:Respuesta más larga
Aquí hay una demostración completa, fácilmente replicable, usando dos métodos, la función incorporada,
input
(usoraw_input
en Python 2) ysys.stdin
. Los datos no se modifican, por lo que el procesamiento no funciona.Para empezar, creemos un archivo para entradas:
Y usando el código que ya hemos visto, podemos verificar que hemos creado el archivo:
Aquí está la ayuda
sys.stdin.read
de Python 3: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 (complementandoprint
, lo que agrega una nueva línea por defecto). Esto ocurre hasta que obtiene EOF (Fin del archivo), momento en el que se elevaEOFError
.Por lo tanto, así es como puede usar
input
en Python 3 (oraw_input
en Python 2) para leer desde stdin, por lo que creamos un módulo de Python que llamamos stdindemo.py:Y imprimámoslo nuevamente para asegurarnos de que es como esperamos:
Nuevamente,
input
lee hasta la nueva línea y esencialmente la elimina de la línea.print
agrega una nueva línea. Entonces, mientras ambos modifican la entrada, sus modificaciones se cancelan. (Por lo tanto, son esencialmente el complemento del otro).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:
O simplemente podemos redirigir el archivo desde stdin:
También podemos ejecutar el módulo como un script:
Aquí está la ayuda sobre la construcción
input
de Python 3: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 iterador. El método complementario para escribir en stdout desde esta entrada es simplemente usarsys.stdout.write
:Imprima de nuevo para asegurarse de que se ve bien:
Y redirigiendo las entradas al archivo:
Golfed en un comando:
Descriptores de archivo para golf
Dado que los descriptores de archivo para
stdin
ystdout
son 0 y 1 respectivamente, también podemos pasarlos aopen
Python 3 (no a 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 2 también
io.open
hace esto, pero la importación ocupa mucho más espacio: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 comostr.join
funciona cuando no se le da una lista), por contraste:La respuesta principal sugiere:
Pero, dado que
sys.stdin
implementa la API de archivo, incluido el protocolo de iterador, es lo mismo que esto:Otra respuesta no sugiere esto. Sólo recuerde que si lo hace en un intérprete, usted tiene que hacer Ctrl- dsi estás en Linux o Mac, o Ctrl- zen Windows (después Enter) para enviar el carácter de fin de archivo en el proceso. Además, esa respuesta sugiere
print(line)
, que agrega una'\n'
al final, usarprint(line, end='')
en su lugar (si en Python 2, necesitaráfrom __future__ import print_function
).El caso de uso real
fileinput
es para leer en una serie de archivos.fuente
La respuesta propuesta por otros:
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á líneas como se esperaba.El script correcto para tal caso de uso sería:
ACTUALIZACIÓN
De los comentarios se ha aclarado que en python 2 solo puede 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.
fuente
for line in sys.stdin:
patrón no espera EOF. Pero si prueba en archivos muy pequeños, las respuestas se pueden almacenar. Pruebe con más datos para ver que lee resultados intermedios.print line
no se despertó en 3.1.3, peroprint(line)
sí.for line in sys.stdin:
no "bloquea hasta EOF". Hay un error de lectura anticipada en Python 2 que retrasa las líneas hasta que el búfer correspondiente esté lleno. Es un problema de almacenamiento en búfer que no está relacionado con EOF. Para solucionarlo, usefor line in iter(sys.stdin.readline, ''):
(useio.open()
para archivos ordinarios). No lo necesitas en Python 3.Esto hará eco de la entrada estándar a la salida estándar:
fuente
Sobre la base de todas las respuestas usando
sys.stdin
, también puede hacer algo como lo siguiente para leer desde un archivo de argumentos si existe al menos un argumento, y recurrir a stdin de lo contrario:y úsalo como
o
o incluso
Eso haría que su script Python se comportara como muchos programas GNU / Unix como
cat
,grep
ysed
.fuente
argparse
es una solución fácilEjemplo compatible con las versiones 2 y 3 de Python:
Puede ejecutar este script de muchas maneras:
1. Usando
stdin
o más corto reemplazando
echo
por cadena aquí :2. Usando un argumento de nombre de archivo
3. Usando a
stdin
través del nombre de archivo especial-
fuente
add_argument('--in'
y luego canalizar al script y agregarlo--in -
a la línea de comando. PSin
no es un muy buen nombre para una variable / atributo.in
no es solo un mal nombre para una variable, es ilegal.args.in.read()
generará un error InvalidSyntax debido a lain
palabra clave reservada. Simplemente puede cambiar el nombre parainfile
gustar los documentos de discusión de python do: docs.python.org/3/library/…El siguiente chip de código lo ayudará (leerá todo el bloqueo de stdin
EOF
en una sola cadena):fuente
Estoy bastante sorprendido de que nadie haya mencionado este truco hasta ahora:
en python2 puede soltar la
set()
llamada, pero sería de cualquier manerafuente
readlines
esa división en líneas y luegojoin
otra vez? Puedes escribirprint(sys.stdin.read())
write
regresaNone
, y el tamaño establecido nunca sería mayor que 1 (=len(set([None]))
)Prueba esto:
y compruébalo con:
fuente
Puede leer desde stdin y luego almacenar entradas en "datos" de la siguiente manera:
fuente
data = sys.stdin.read()
sin el problema de las concatenaciones de cadenas repetidas.Leer desde
sys.stdin
, pero para leer datos binarios en Windows , debe tener mucho cuidado, yasys.stdin
que se abre en modo texto y se dañará al\r\n
reemplazarlos\n
.La solución es establecer el modo en binario si se detecta Windows + Python 2, y en Python 3 usar
sys.stdin.buffer
.fuente
Uso el siguiente método, devuelve una cadena de stdin (lo uso para el análisis json). Funciona con pipe y prompt en Windows (aún no se ha probado en Linux). Cuando se le solicita, dos saltos de línea indican el final de la entrada.
fuente
El problema que tengo con la solucion
es que si no pasa ningún dato a stdin, se bloqueará para siempre. Es por eso que me encanta esta respuesta : primero verifique si hay algunos datos en stdin y luego léala. Esto es lo que terminé haciendo:
fuente
select
se llama; o también podría enfrentar problemas si stdin está conectado a un archivo en un medio lento (red, CD, cinta, etc.). Dijiste que "si no pasas ningún dato a stdin, se bloqueará para siempre". es un problema , pero yo diría que es una característica . La mayoría de los programas CLI (por ejemplocat
) funcionan de esta manera, y se espera que lo hagan. EOF es lo único en lo que debe depender para detectar el final de la entrada.Tuve algunos problemas al hacer que esto funcionara para leer sobre sockets conectados a él. Cuando el zócalo 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)
Entonces, si comienza a escuchar en un socket, funcionará correctamente (por ejemplo, en bash):
Y puede llamarlo con telnet o simplemente apuntar un navegador a localhost: 12345
fuente
Con respecto a este:
for line in sys.stdin:
Acabo de probarlo 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 pitónica (y funciona en archivos más grandes):
Entonces puedo ejecutar el script localmente como:
fuente
sys.stdin
como argumento de línea de comandos al script.sys.stdin
como un argumento de línea de comandos al script? Los argumentos son cadenas y las secuencias son objetos en forma de archivo, no son lo mismo.sys.stdin
es un objeto similar a un archivoPara Python 3 eso sería:
Esta es básicamente una forma simple de cat (1), ya que no agrega una nueva línea después de cada línea. Puede usar esto (después de haber marcado el archivo ejecutable usando
chmod +x cat.py
:fuente
Hay
os.read(0, x)
que lee xbytes de 0 que representa stdin. Esta es una lectura sin búfer, más bajo nivel que sys.stdin.read ()fuente
Al usar el
-c
comando, como una forma complicada, en lugar de leer elstdin
(y más flexible en algunos casos), también puede pasar un comando de script de shell a su comando de Python poniendo el comando de venta entre comillas dentro de un paréntesis que comienza con un$
signo.p.ej
Esto contará el número de líneas del archivo histórico de goldendict.
fuente