Obtener stdin de una tubería con nombre

10

Lo que estoy tratando de hacer es ejecutar python en una ventana de terminal y redirigir su stdin desde una tubería con nombre. Luego escribo en la tubería con nombre en otra terminal y hago que ese comando se ejecute en python.

Terminal 1:

mkfifo p1
python < p1

Terminal 2:

echo -n "print \"Hello World\"" > p1

Lo que sucede es que Python imprime Hello Worldy sale. Lo que quiero hacer es mantener Python ejecutándose para tomar el siguiente comando. ¿Cómo hago esto en el shell?

Lord Loh
fuente

Respuestas:

10

Necesitas

  • Ejecute Python de forma interactiva aunque su stdin no sea una terminal: use python -i
  • mantenga abierto el extremo de escritura de la tubería; de lo contrario, Python detectará EOF y saldrá.

Entonces:

python -i < p1

Y en otra parte:

exec 3> p1
echo '1j*1j' >&3
...
# and when done, close that file descriptor so python sees the EOF:
exec 3>&-
Stéphane Chazelas
fuente
¡Gracias! Funcionó. No estoy familiarizado con lo que has hecho. ¿Podría agregar algunos detalles a su respuesta para explicar lo que está sucediendo? ¿Qué está exec 3> p1haciendo y qué es &3y exec 3> &1? Gracias.
Lord Loh
1
Su respuesta me recordó a este banner: sphotos-b.xx.fbcdn.net/hphotos-ash4/ ... es la foto de portada de un amigo en Facebook :-)
Lord Loh.
Una pregunta, ¿ exec 3>&-funcionaría igual que exec 3>&1aquí?
Comodín el
1
@Wildcard Sospecho que tenía la intención de escribir 3>&-aquí. 3>&1funcionaría bien pero tiene poco sentido. Gracias
Stéphane Chazelas
5

Puede usar tail -fpara mantener abierto el fifo después de echoescribir en él.

tail -n1 -f p1 | python

Por que esto funciona

pythonestá leyendo de p1. Cuando llega al final del archivo, deja de leer. Este es un comportamiento normal para las lecturas de archivos, incluso si el archivo es una tubería con nombre. tailcon el -findicador (seguir) se seguirá leyendo desde un archivo una vez que se llegue a su fin.


fuente
Intenté echo "print \"Hello World\" " > p1en la segunda terminal y no pasó nada, pero la terminal tampoco estaba bloqueada. El terminal con Python permaneció bloqueado hasta que ^clo cerré y salí y terminé Python con un mensaje de interrupción de teclado que Python muestra.
Lord Loh
Usé este tail -ftruco al descomprimir el archivo tar dividido en bloques a través de una tubería con nombre. Funcionó maravillosamente.
Mael
2

Debe enviar todo el programa a la vez.

Cuando llama a ejecutar, python < p1el shell está esperando la entrada antes de invocar python. Es decir, Python ni siquiera comienza a ejecutarse en absoluto hasta que el shell ha leído todo el flujo de datos y luego se lo pasa en su totalidad a python.

Incluso si se ejecuta en su python -u p1lugar (es decir, sin búfer y leído desde un archivo p1) pythonintentará leer todo el archivo antes de ejecutarlo.

Prueba este experimento.

Terminal 1:

mkfifo p1
python < p1

Terminal 2:

cat > p1
print "Hello World"
print "Hello World"

Verá que puede enviar varias líneas, pero Python en el Término 1 no hace nada. Ahora presiona ctrl+ D. Todo el programa se ejecuta a la vez.

Entonces, para resumir, si desea que Python lea desde una tubería, debe enviar todo el programa. No puedes usar Python de manera interactiva de esta manera.

bahamat
fuente
1

Quizás el enfoque de cola es mejor (más flexible) pero como alternativa:

{ echo -n "print \"Hello World\""; cat; } > p1
Hauke ​​Laging
fuente
Esto no funciona como yo quiero. -npodría haber sido eliminado. Y después de eso, 0. El terminal con el echocomando se bloquea 1. python no ejecuta el comando hasta que presiono ^cel echoterminal y ambos procesos finalizan.
Lord Loh
1
@LordLoh. Puede ser un problema de almacenamiento en búfer. Probablemente Python ejecutará el comando si se ha creado suficiente salida para que la primera línea finalmente se escriba en el FIFO. Pero como hay una solución que funciona, no tendría sentido esforzarse para resolver este problema.
Hauke ​​Laging