В 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 |
…и так далее: Ctrl—C для выхода…
[C:\…\PP4E\System\Processes]$ file /tmp/pipefifo # окно потомка
/tmp/pipefifo: fifo (named pipe)
[C:\…\PP4E\System\Processes]$ python pipefifo.py -child
…Ctrl—C для выхода…
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011