Кажется, что труба может быть подходящим выбором для вашего случая использования. Имейте в виду, что при нормальных обстоятельствах чтение и запись ожидают, что данные будут записаны или использованы соответственно. Также убедитесь, что вы не удивитесь буферизации (ничего не произойдет, потому что буфер не будет автоматически очищаться, если только на ожидаемой границе, если не установлено соответственно).
Базовый пример того, как две трубы (они однонаправлены) могут использоваться между двумя процессами:
import os
def child():
"""
This function is executed in a child process.
"""
infile = os.fdopen(r1)
outfile = os.fdopen(w2, 'w', buffering=1)
for line in infile:
if line.rstrip() == 'quit':
break
outfile.write(line.upper())
def parent():
"""
This function is executed in a parent process.
"""
outfile = os.fdopen(w1, 'w', buffering=1)
infile = os.fdopen(r2)
print('Foo', file=outfile)
print(infile.readline(), end='')
print('bar', file=outfile)
print(infile.readline(), end='')
print('quit', file=outfile)
(r1, w1) = os.pipe() # for parent -> child writes
(r2, w2) = os.pipe() # for child -> parent writes
pid = os.fork()
if pid == 0:
child() # child code runs here.
elif pid > 0:
parent() # parent code runs here.
os.waitpid(pid, 0) # wait for child
else:
raise RuntimeError("This should not have happened.")
# Once returned from corresponding function, both processes exit
Действительно, было бы проще и практичнее использовать subprocess
, и вы, вероятно, захотите exec
другой двоичный файл / файл. Прежнему нужно было бы сказать, чтобы он не закрывал (по крайней мере, соответствующий канал) файловые дескрипторы, второму требовалось бы, чтобы дескрипторы файлов канала были наследуемыми (не установлен флаг O_CLOEXEC
). В остальном то же, что и выше.
Код ребенка:
import os
import sys
infile = os.fdopen(int(sys.argv[1]))
outfile = os.fdopen(int(sys.argv[2]), 'w', buffering=1)
for line in infile:
if line.rstrip() == 'quit':
break
outfile.write(line.upper())
Родительский скрипт:
import os
import subprocess
(r1, w1) = os.pipe2(0) # for parent -> child writes
(r2, w2) = os.pipe2(0) # for child -> parent writes
child = subprocess.Popen(['./child.py', str(r1), str(w2)], pass_fds=(r1, w2))
outfile = os.fdopen(w1, 'w', buffering=1)
infile = os.fdopen(r2)
print('Foo', file=outfile)
print(infile.readline(), end='')
print('bar', file=outfile)
print(infile.readline(), end='')
print('quit', file=outfile)
child.wait()
Если подумать об этом, я забыл спросить, нужен ли ребенку стандартный ввод / вывод для чего-либо, или его можно было бы использовать для ввода / вывода информации. Это было бы еще проще:
Ребенок:
import sys
for line in sys.stdin:
if line.rstrip() == 'quit':
break
print(line.upper(), end='', flush=True)
Родитель:
import os
import subprocess
(r1, w1) = os.pipe2(0) # for parent -> child writes
(r2, w2) = os.pipe2(0) # for child -> parent writes
child = subprocess.Popen(['./child.py'], stdin=r1, stdout=w2)
outfile = os.fdopen(w1, 'w', buffering=1)
infile = os.fdopen(r2)
print('Foo', file=outfile)
print(infile.readline(), end='')
print('bar', file=outfile)
print(infile.readline(), end='')
print('quit', file=outfile)
child.wait()
Как уже говорилось, на самом деле это не специфично для Python, и это лишь грубые подсказки о том, как можно использовать каналы как один из вариантов.