2013-07-03 4 views
7

Я хочу использовать os.mkfifo для простой связи между программами. У меня проблема с чтением из fifo в цикле.fifo - чтение в петле

Рассмотрите этот пример игрушки, где у меня есть читатель и писатель, работающий с fifo. Я хочу иметь возможность запускать читателя в цикле, чтобы читать все, что входит в fifo.

# reader.py 
import os 
import atexit 

FIFO = 'json.fifo' 

@atexit.register 
def cleanup(): 
    try: 
     os.unlink(FIFO) 
    except: 
     pass 

def main(): 
    os.mkfifo(FIFO) 
    with open(FIFO) as fifo: 
#  for line in fifo:    # closes after single reading 
#  for line in fifo.readlines(): # closes after single reading 
     while True: 
      line = fifo.read()   # will return empty lines (non-blocking) 
      print repr(line) 

main() 

И писатель:

# writer.py 
import sys 

FIFO = 'json.fifo' 


def main(): 
    with open(FIFO, 'a') as fifo: 
     fifo.write(sys.argv[1]) 

main() 

Если я бегу python reader.py и позже python writer.py foo, «Foo» будет напечатано, но ФИФО будет закрыта, и читатель будет выходить (или вращение внутри цикла while). Я хочу, чтобы читатель оставался в цикле, поэтому я могу много раз писать сценаристу.

Редактировать

Я использую этот фрагмент кода для обработки вопроса:

def read_fifo(filename): 
    while True: 
     with open(filename) as fifo: 
      yield fifo.read() 

, но может быть, есть какой-то аккуратнее способ справиться с этим, вместо того, чтобы повторно открыть файл ...

ответ

2

FIFO работает (на стороне читателя) именно таким образом: она может быть прочитана, пока все писатели не исчезнут. Затем он сигнализирует EOF читателю.

Если вы хотите, чтобы читатель продолжал читать, вам нужно будет снова открыть и прочитать оттуда. Таким образом, ваш фрагмент - это именно то, что нужно.

Если у вас есть несколько авторов, вам необходимо убедиться, что каждая записанная ими часть данных меньше PIPE_BUF, чтобы не перепутать сообщения.

+0

Я полагаю, что для нескольких авторов я должен использовать что-то более причудливое, потому что здесь писатели будут закрывать друг друга FIFO? И эти данные от одного автора могут быть смешаны с данными другого автора –

+0

Они не закрывают друг друга, и если записанные данные достаточно малы, они также не мешают. Существует постоянная 'PIPE_BUF', которая сообщает вам, насколько большими могут быть пакеты данных, не мешая друг другу. – glglgl

1

Вам не нужно повторно открывать файл повторно. Вы можете использовать select для блокировки до тех пор, пока не будут доступны данные.

with open(FIFO_PATH) as fifo: 
    while True: 
     select.select([fifo],[],[fifo]) 
     data = fifo.read() 
     do_work(data) 

В этом примере вы не будете читать EOF.

Смежные вопросы