Obtenir stdin à partir d'un canal nommé

10

Ce que j'essaie de faire, c'est d'exécuter python dans une fenêtre de terminal et de rediriger son stdin à partir d'un canal nommé. Ensuite, j'écris dans le canal nommé dans un autre terminal et je fais exécuter cette commande sur python.

Terminal 1:

mkfifo p1
python < p1

Terminal 2:

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

Ce qui se passe, c'est que python imprime Hello Worldet quitte. Ce que je veux faire, c'est continuer à exécuter python pour prendre une prochaine commande. Comment faire cela dans le shell?

Lord Loh.
la source

Réponses:

10

Tu dois

  • Exécutez python de manière interactive même si son stdin n'est pas un terminal: utilisez python -i
  • garder l'extrémité d'écriture du tuyau ouverte, sinon python détectera EOF et quittera.

Donc:

python -i < p1

Et ailleurs:

exec 3> p1
echo '1j*1j' >&3
...
# and when done, close that file descriptor so python sees the EOF:
exec 3>&-
Stéphane Chazelas
la source
Merci! Ça a marché. Je ne connais pas ce que vous avez fait. Pourriez-vous ajouter quelques détails à votre réponse pour expliquer ce qui se passe. Que exec 3> p1fait-on et qu'est-ce que &3& exec 3> &1? Je vous remercie.
Lord Loh.
1
Votre réponse m'a rappelé cette bannière - sphotos-b.xx.fbcdn.net/hphotos-ash4/… c'est la photo de couverture d'un ami sur facebook :-)
Lord Loh.
Une question, exec 3>&-fonctionnerait la même chose exec 3>&1qu'ici?
Wildcard
1
@Wildcard Je soupçonne que j'avais l'intention d'écrire 3>&-ici. 3>&1fonctionnerait aussi bien mais aurait peu de sens. Merci
Stéphane Chazelas
5

Vous pouvez utiliser tail -fpour garder le fifo ouvert après les echoécritures.

tail -n1 -f p1 | python

Pourquoi cela fonctionne

pythonlit de p1. Lorsqu'il atteint la fin du fichier, il arrête la lecture. Il s'agit d'un comportement normal pour les lectures de fichiers, même si le fichier est un canal nommé. tailavec le -fdrapeau (suivre) continuera la lecture d'un fichier une fois sa fin atteinte.


la source
J'ai essayé echo "print \"Hello World\" " > p1dans le deuxième terminal et rien ne s'est passé - mais le terminal n'était pas bloqué non plus. Le terminal avec python est resté bloqué jusqu'à ce que je le ^cquitte et le quitte et termine python avec un message d'interruption clavier affiché par python.
Lord Loh.
J'ai utilisé cette tail -fastuce lors du déballage de l'archive tar fractionnée en bloc via un canal nommé. Cela a fonctionné à merveille.
Mael
2

Vous devez envoyer le programme entier en une seule fois.

Lorsque vous appelez run, python < p1le shell attend une entrée avant d'appeler python. Autrement dit, python ne commence même pas du tout à s'exécuter tant que le flux de données entier n'a pas été lu par le shell, puis transmis dans son intégralité à python.

Même en exécutant à la python -u p1place (c'est-à-dire sans tampon et en lisant à partir du fichier p1) python, vous essayez de lire l'intégralité du fichier avant de l'exécuter.

Essayez cette expérience.

Terminal 1:

mkfifo p1
python < p1

Terminal 2:

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

Vous verrez que vous pouvez envoyer plusieurs lignes mais python dans Term 1 ne fait rien. Appuyez maintenant sur ctrl+ D. L'ensemble du programme s'exécute simultanément.

Donc, pour résumer, si vous voulez que python lise à partir d'un canal, vous devez envoyer le programme entier. Vous ne pouvez pas utiliser python de manière interactive de cette façon.

bahamat
la source
1

Peut-être que l'approche queue est meilleure (plus flexible) mais comme alternative:

{ echo -n "print \"Hello World\""; cat; } > p1
Hauke ​​Laging
la source
Cela ne fonctionne pas comme je le souhaite. -npourrait avoir été supprimé. Et après cela, 0. Le terminal avec la echocommande est bloqué 1. python n'exécute pas la commande jusqu'à ce que j'appuie sur ^cle echoterminal et que les deux processus se terminent.
Lord Loh.
1
@LordLoh. Peut être un problème de mise en mémoire tampon. Python exécutera probablement la commande si suffisamment de sortie a été créée pour que la première ligne soit finalement écrite dans le FIFO. Mais comme il existe une solution de travail, il ne serait pas logique de faire des efforts pour résoudre ce problème.
Hauke ​​Laging