2016-08-22 4 views
0

У меня есть именованный канал в linux, и я хочу его прочитать из python. Проблема в том, что процесс python «потребляет» одно ядро ​​(100%) непрерывно. Мой код выглядит следующим образом:Python read named PIPE

FIFO = '/var/run/mypipe' 
os.mkfifo(FIFO) 
with open(FIFO) as fifo: 
    while True: 
     line = fifo.read() 

Я хочу спросить, если «сна» поможет ситуации или процесс, идущий к потере некоторых входных данных из трубы. Я не могу управлять входом, поэтому я не знаю частоты ввода данных. Я читал о выборе и опросе, но я не нашел примера для моей проблемы. Наконец, я хочу спросить, влияет ли 100% -ное использование на ввод данных (потеря или что-то?).

Редактировать: Я не хочу прерывать цикл. Я хочу, чтобы процесс выполнялся непрерывно и «слышит» данные из трубы.

+0

Что 'печать (строка)' выход в цикле? И как вы на это пишете? –

+0

Скрипт ожидает данных из другого процесса. Если он принимает строку со специальной строкой, она выполняет некоторые вызовы api. – user1005633

+0

Итак, вы постоянно видите данные в цикле, когда вы 'print (line)'? –

ответ

6

В типичной UNIX моды, read(2) возвращает 0 байт, чтобы указать конец-в-файл, который может означать:

  • Там нет больше байт в файле
  • Другой конец сокета выключился в подключение
  • писатель закрыл трубу

В вашем случае, fifo.read() возвращает пустую строку, потому что писатель закрыл свой файловый дескриптор ,

Вы должны обнаружить, что случай и выйти из вашего цикла:

reader.py:

import os 
import errno 

FIFO = 'mypipe' 

try: 
    os.mkfifo(FIFO) 
except OSError as oe: 
    if oe.errno != errno.EEXIST: 
     raise 

print("Opening FIFO...") 
with open(FIFO) as fifo: 
    print("FIFO opened") 
    while True: 
     data = fifo.read() 
     if len(data) == 0: 
      print("Writer closed") 
      break 
     print('Read: "{0}"'.format(data)) 

Пример сеанса

Терминал 1:

$ python reader.py 
Opening FIFO... 
<blocks> 

Терминал 2:

$ echo -n 'hello' > mypipe 

Терминал 1:

FIFO opened 
Read: "hello" 
Writer closed 
$ 

Update 1 - Непрерывно повторно открыть

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

Чтобы сделать это эффективно, вы можете (и должны) использовать тот факт, что

Обычно, не открывая блоки FIFO до другого конца открыт также.

Здесь я добавляю еще один цикл вокруг open и цикл read.Таким образом, после того, как труба закрыта, код будет пытаться повторно открыть его, что не будет блокировать до другого писателя открывает трубу:

import os 
import errno 

FIFO = 'mypipe' 

try: 
    os.mkfifo(FIFO) 
except OSError as oe: 
    if oe.errno != errno.EEXIST: 
     raise 

while True: 
    print("Opening FIFO...") 
    with open(FIFO) as fifo: 
     print("FIFO opened") 
     while True: 
      data = fifo.read() 
      if len(data) == 0: 
       print("Writer closed") 
       break 
      print('Read: "{0}"'.format(data)) 

Терминал 1:

$ python reader.py 
Opening FIFO... 
<blocks> 

Терминал 2:

$ echo -n 'hello' > mypipe 

Терминал 1:

FIFO opened 
Read: "hello" 
Writer closed 
Opening FIFO... 
<blocks> 

Терминал 2:

$ echo -n 'hello' > mypipe 

Терминал 1:

FIFO opened 
Read: "hello" 
Writer closed 
Opening FIFO... 
<blocks> 

... и так далее.


Вы можете узнать больше, прочитав man страницу для труб:

+0

Я не хочу разорвать петлю. Я хочу постоянно читать. Сценарий ожидает данных от другого процесса. Если он принимает строку с определенной строкой, она выполняет некоторые вызовы api ... – user1005633

+0

* «Я хочу постоянно читать из нее». * Нет, вы этого не делаете. Это то, что приводит к 100% использованию процессора. Как вы можете видеть в моем обновленном примере, 'open' блокируется до тех пор, пока не появится писатель. То, что вы хотите сделать, это закрыть трубку, а затем разрешить 'open' блокировать при повторном открытии. См. Мое обновление 1. –

+0

Я настоятельно рекомендую вам полностью прочитать страницы с людьми, с которыми я связан, и полностью понять семантику открытия, чтения и написания труб/fifos. –