2016-06-09 6 views
1

Um mit einer Shell zu kommunizieren, die einmal gestartet wird und in einem separaten Prozess ausgeführt wird, habe ich Popenfrom subprocess verwendet.mit FIFOs für Eingabe und Ausgabe in Python

import os 
from subprocess import Popen, PIPE 

def server(): 
    FIFO_PATH = '/tmp/my_fifo' 
    FIFO_PATH2 = '/tmp/in_fifo' 
    if os.path.exists(FIFO_PATH): 
     os.unlink(FIFO_PATH) 
    if os.path.exists(FIFO_PATH2): 
     os.unlink(FIFO_PATH2) 

    if not os.path.exists(FIFO_PATH2): 
     os.mkfifo(FIFO_PATH2) 
     in_fifo = open(FIFO_PATH2, 'rw+') 
     print "in_fifo:", in_fifo 

    if not os.path.exists(FIFO_PATH): 
     os.mkfifo(FIFO_PATH) 
     my_fifo = open(FIFO_PATH, 'rw+') 
     print "my_fifo:", my_fifo 

    p = Popen(['python', '-u', 'shell.py'], shell=False, stdin=in_fifo, stdout=my_fifo) 

def read(): 
    FIFO_PATH = '/tmp/my_fifo' 
    i=0 
    while i < 10: 
     ++i 
     print i, open(FIFO_PATH, 'r').readline() 

def write(input): 
    FIFO_PATH2 = '/tmp/in_fifo' 

    pipe = open(FIFO_PATH2, 'w+') 
    pipe.write(input+'\n') 

def test(): 
    server() 
    write('test') 
    read() 

und die shell.py

Input = ' ' 
print 'shell called' 
while Input!= 'z': 
    Input=raw_input() 
    print 'input ', Input 

    if Input != '': 
     if Input == 'test': 
      print 'Yeehhaaaaa it works' 

so nennen test() geben folgendes Ergebnis

in_fifo: <open file '/tmp/in_fifo', mode 'rw+' at 0x7f0a4e17ed20> 
my_fifo: <open file '/tmp/my_fifo', mode 'rw+' at 0x7f0a4e17edb0> 
0 shell called 

0 input test 

Fragen

Warum ist nur die erste Zeile gedruckt? Wie drucke ich alle Zeilen?

Auch bin ich mir nicht sicher über die richtige Verwendung von FIFOs. Vielleicht gibt es bessere Möglichkeiten, dies zu tun. Ich bin offen für irgendwelche Vorschläge.

p Mit p.stdin.write() und p.stdout.readline() zu nennen, ist keine Lösung für mich, weil ich die Funktionen von JavaScript aufrufen, ohne p die Instanz zu haben.

Antwort

0

Aus der Manpage für mkfifo:

einen FIFO-Öffnung für das Lesen normalerweise blockiert, bis ein anderer Prozess den gleichen FIFO zum Schreiben öffnet, und umgekehrt. Siehe fifo (7) für die nicht blockierende Behandlung von FIFO-Spezialdateien.

Also das zweite Mal, wenn Sie den FIFO zum Lesen öffnen, blockiert der Anruf. Dies kann nach dem Drücken von Strg + C in der Zurückverfolgungs zu sehen:

^CTraceback (most recent call last): 
0 
Traceback (most recent call last): 
    File "shell_fifo.py", line 51, in <module> 
    File "shell.py", line 4, in <module> 
    test() 
    File "shell_fifo.py", line 48, in test 
     read() 
    File "shell_fifo.py", line 29, in read 
    print i, open(FIFO_PATH, 'r').readline() # read() is blocked here 
KeyboardInterrupt 
Input=raw_input() 
KeyboardInterrupt 

ändern read Funktion, so dass es nur ein einziges Mal den FIFO öffnet:

def read(): 
    FIFO_PATH = '/tmp/my_fifo' 
    i = 0 
    with open(FIFO_PATH, 'r') as read_fifo: 
     while i < 10: 
      i += 1 
      print i, read_fifo.readline().rstrip() 

Sie sollten Ausgabe wie folgt sehen:

in_fifo: <open file '/tmp/in_fifo', mode 'rw+' at 0x7f1ba655b5d0> 
my_fifo: <open file '/tmp/my_fifo', mode 'rw+' at 0x7f1ba655b540> 
1 shell called 
2 input test 
3 Yeehhaaaaa it works 
+0

Vielen Dank es funktioniert. Aber wie kann ich feststellen, ob Fifo leer ist? denn wenn ich readline() lese und nichts zu lesen ist, wartet es für immer. vielleicht könnte ich irgendwie eine Auszeit nehmen? – Maori

+0

ok Ich mache Dinge mit os.open(), os.read() und fangen die Ausnahme mit errno == EAGAIN – Maori

Verwandte Themen