Как правильно писать в FIFO на Python? - PullRequest
17 голосов
/ 13 августа 2011

Что-то очень странное происходит, когда я открываю FIFO (именованные каналы) в Python для записи. Подумайте, что происходит, когда я пытаюсь открыть FIFO для записи в интерактивном переводчике:

>>> fifo_write = open('fifo', 'w')

Вышеупомянутые блоки строк, пока я не открою другой интерпретатор и не наберу следующее:

>>> fifo_read = open('fifo', 'r')
>>> fifo.read()

Я не понимаю, почему мне пришлось ждать открытия канала для чтения, но давайте пропустим это. Приведенный выше код будет блокироваться, пока данные не станут доступными, как ожидалось. Однако, допустим, я возвращаюсь к первому окну интерпретатора и набираю:

>>> fifo_write.write("some testing data\n")
>>> fifo_write.flush()

Ожидаемое поведение - во втором интерпретаторе будет возвращен вызов read, и мы увидим данные на экране, за исключением того, что со мной ничего не происходит. Если я позвоню os.fsync, произойдет следующее:

>>> import os
>>> fifo_write.flush()
>>> os.fsync(fifo_write.fileno())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument

И читатель fifo все еще ждет. Однако, если я позвоню fifo_writer.close(), то данные сбрасываются. Если я использую команду оболочки для подачи канала:

$ echo "some data" > fifo

тогда вывод читателя будет:

>>> fifo_read.read()
'some data\n'

Кто-нибудь испытывал это? Если так, есть ли обходной путь для этого? Моя текущая ОС - Ubuntu 11.04 с Linux 2.6.38.

Ответы [ 2 ]

10 голосов
/ 13 августа 2011

read() не возвращается, пока не достигнет EOF.

Вы можете попробовать указать количество байтов, которые вы хотите прочитать, например read(4).Он будет блокироваться до тех пор, пока не будет записано достаточное количество байтов, поэтому производитель должен записать как минимум столько байтов, а затем вызвать flush().

3 голосов
/ 06 сентября 2013

Чтобы избежать необходимости очистки, откройте файл без буферизации:

fifo_read = open('fifo', 'r', 0)

Это удалит буферизацию высокого уровня.Данные поступают в ОС напрямую, и, будучи FIFO, они фактически никогда не записываются на диск, а передаются прямо в считыватель через буфер FIFO, поэтому вам не нужно синхронизировать.сначала создали fifo с os.mkfifo() или mkfifo в оболочке, как вы указали в комментарии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...