2016-06-09 51 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