Основы именованных каналов

osnovy imenovannyh kanalov Системные инструменты параллельного выполнения

В Python файлы именованных каналов создаются с помощью функции os.mkfifo, которая доступна в настоящее время только в Unix-подобных системах и в версии Python для Cygwin в Windows, но недоступна в стандартной версии Python для Windows. Эта функция просто создает внешний файл — для отправки и получения данных через fifo его нужно открывать и обрабатывать, как стандартный файл.

Для иллюстрации в примере 5.24 приводится измененная версия сценария pipe2.py из примера 5.20, в которой вместо анонимных каналов используются именованные каналы. Как и сценарий pipe2.py, эта версия открывает в дочернем процессе канал fifo с помощью функции os.open в режиме двоичного доступа, а в родительском процессе — с помощью встроенной функции open, в текстовом режиме. Вообще говоря, на любом конце канала можно использовать любой из предложенных приемов, чтобы интерпретировать данные в канале как двоичные данные или как текст.

Пример 5.24. PP4E\System\Processes\pipefifo.py

именованные каналы; функция os.mkfifo недоступна в Windows (без Cygwin); здесь нет необходимости использовать прием ветвления процессов, потому что файлы каналов fifo являются внешними по отношению к процессам — совместное использование дескрипторов файлов в родителе/потомке здесь неактуально;

import os, time, sys

fifoname = ‘/tmp/pipefifo # имена должны быть одинаковыми

def child():

pipeout = os.open(fifoname, os.O_WRONLY) # открыть fifo как дескриптор zzz = 0

while True:

time.sleep(zzz)

msg = (‘Spam %03d\n’ % zzz).encode() # был открыт в двоичном режиме os.write(pipeout, msg) zzz = (zzz+1) % 5

def parent():

pipein = open(fifoname, ‘r’) # открыть fifo как текстовый файл

while True:

line = pipein.readline()[:-1] # блокируется до отправки данных

print(‘Parent %d got “%s” at %s’ % (os.getpid(), line, time.time()))

if __name__ == ‘__main__’:

if not os.path.exists(fifoname):

os.mkfifo(fifoname) # создать именованный канал

if len(sys.argv) == 1:

parent() # если нет аргументов — запустить как родительский процесс else: # иначе — как дочерний процесс

child()

Поскольку канал fifo существует независимо от родительского и дочернего процессов, нет никакой необходимости использовать прием ветвления процессов: дочерний процесс может быть запущен независимо от родительского и должен лишь открыть файл fifo с таким же именем. Ниже, например, в Cygwin, родитель запущен в одном окне командной строки, а потомок — в другом. Сообщения начинают появляться в окне родителя только после того, как потомок будет запущен и начнет записывать сообщения в файл fifo:

[C:\\PP4E\System\Processes] $ python pipefifo.py # окно родителя

Parent 8324 got

“Spam 000”

at 1268003696.07

Parent 8324 got

“Spam 001”

at 1268003697.06

Parent 8324 got

“Spam 002”

at 1268003699.07

Parent 8324 got

“Spam 003”

at 1268003702.08

Parent 8324 got

“Spam 004”

at 1268003706.09

Parent 8324 got

“Spam 000”

at 1268003706.09

Parent 8324 got

“Spam 001”

at 1268003707.11

Parent 8324 got

“Spam 002”

at 1268003709.12

Parent 8324 got

“Spam 003”

at 1268003712.13

Parent 8324 got

“Spam 004”

at 1268003716.14

Parent 8324 got

“Spam 000”

at 1268003716.14

Parent 8324 got

“Spam 001”

at 1268003717.15

…и так далее: CtrlC для выхода…

 

[C:\\PP4E\System\Processes]$ file /tmp/pipefifo # окно потомка

/tmp/pipefifo: fifo (named pipe)

[C:\\PP4E\System\Processes]$ python pipefifo.py -child

CtrlC для выхода…

Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011

Оцените статью
Секреты программирования
Добавить комментарий