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

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

Поскольку анонимные каналы являются наиболее традиционным инструментом, мы познакомимся с ними в первую очередь. Сценарий в примере 5.19 создает копию вызывающего процесса с помощью функции os.fork (с ветвлением процессов мы познакомились выше в этой главе). После ветвления исходный родительский процесс и его дочерняя копия общаются между собой через канал, созданный функцией os.pipe перед ветвлением. Функция os.pipe возвращает кортеж с двумя дескрипторами файлов — низкоуровневыми идентификаторами файлов, с которыми мы познакомились в главе 4, представляющими входной и выходной концы канала. Так как ответвленный дочерний процесс получает копии дескрипторов файлов своего родителя, то при записи в дескриптор выходного конца канала в дочернем процессе данные посылаются обратно родителю по каналу, созданному до создания дочернего процесса.

Пример 5.19. PP4E\System\Processes\pipe1.py

import os, time

def child(pipeout):

zzz = 0

while True:

time.sleep(zzz) # заставить родителя подождать

msg = (‘Spam %03d% zzz).encode() # каналы двоичные файлы os.write(pipeout, msg) # отправить данные родителю

zzz = (zzz+1) % 5 # переход к 0 после 4

подпись: def parent():
pipein, pipeout = os.pipe()
if os.fork() == 0:
child(pipeout)
else:
while true:
line = os.read(pipein, 32)
подпись: # создать канал с 2 концами
# создать копию процесса
# в копии вызвать child
# в родителе слушать канал
# остановиться до получения данных

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

parent()

Если запустить эту программу в Linux, Cygwin или в другой Unixподобной системе (функция pipe имеется в стандартной реализации Python для Windows, а вот функция fork — нет), то родительский процесс при каждом вызове os.read будет ждать, пока дочерний процесс отправит данные в канал. Здесь дочерний и родительский процессы действуют почти как клиент и сервер — родитель запускает дочерний процесс и ждет от него инициации обмена.[XVIII] Для имитации длительных операций дочерний процесс заставляет родителя ждать каждое следующее сообщение на одну секунду дольше предыдущего с помощью вызова функции time.sleep, пока задержка не достигнет четырех секунд. Когда счетчик задержки zzz становится равным 005, он сбрасывается обратно в 000, и отсчет начинается сначала:

[C:\\PP4E\System\Processes]$ python pipe1.py

Parent 6716

got

[b’Spam 000’]

at

1267996104.53

Parent 6716

got

[b’Spam 001’]

at

1267996105.54

Parent 6716

got

[b’Spam 002’]

at

1267996107.55

Parent 6716

got

[b’Spam 003’]

at

1267996110.56

Parent 6716

got

[b’Spam 004’]

at

1267996114.57

Parent 6716

got

[b’Spam 000’]

at

1267996114.57

Parent 6716

got

[b’Spam 001’]

at

1267996115.59

Parent 6716

got

[b’Spam 002’]

at

1267996117.6

Parent 6716

got

[b’Spam 003’]

at

1267996120.61

Parent 6716

got

[b’Spam 004’]

at

1267996124.62

Parent 6716

got

[b’Spam 000’]

at

1267996124.62

Parent 6716

got

[b’Spam 001’]

at

1267996125.63

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

Обратите внимание, что родитель принимает из канала строку байтов. Данные через простые каналы обычно передаются в виде строк байтов, если они обслуживаются с применением инструментов для работы с дескрипторами файлов, с которыми мы встречались в главе 4 (как мы видели там, инструменты чтения из дескрипторов и записи в дескрипторы, имеющиеся в модуле os, всегда возвращают и принимают строки байтов). Именно поэтому мы вынуждены в дочернем процессе вручную кодировать текст в строку байтов перед записью в канал — операция форматирования строк не может применяться к строкам байтов. Как будет показано в следующем разделе, дескриптор канала можно обернуть объектом текстового файла, как мы делали это в примерах главы 4, но этот прием обеспечит лишь автоматическое кодирование и декодирование при передаче данных средствами объекта, тогда как внутри канала данные все равно будут передаваться в форме строк байтов.

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

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