2016-06-09 53 views
1

要與一個啓動一次並在單獨進程中運行的shell進行通信,我使用了Popenfrom subprocess使用FIFOs在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() 

shell.py

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

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

所以調用test()給出的結果

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 

問題

爲什麼只有第一行印?如何打印所有行?

此外我不確定正確使用FIFO。也許有更好的方法來完成這件事。我接受任何建議。

使用p調用p.stdin.write()p.stdout.readline()對我來說是無解的,因爲我必須從JavaScript調用的功能,而無需實例p

回答

0

從手冊頁mkfifo

打開FIFO讀取正常阻塞,直到一些其它進程打開的寫作相同的FIFO,反之亦然。有關FIFO特殊文件的非阻塞處理,請參閱fifo(7)。

因此,第二次打開FIFO讀取,呼叫塊。這可以回溯可以看出按下Ctrl + C後:

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() 

你應該看到輸出類似這樣:

^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 
,使其只打開FIFO一次

更改read功能

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

非常感謝你的工作。 但是,如何確定FIFO是否爲空?因爲如果我做readline(),就沒有什麼可讀的,它會永遠等待。也許我可以以某種方式使用超時? – Maori

+0

好的我用os.open(),os.read()完成事情,並用errno == EAGAIN捕獲異常 – Maori