Sim, usar exec e herdar o mesmo pid como pai significa que o filho mantém as conexões de pipe por padrão, desde que os descritores de arquivo não sejam marcados como close-on-exec (o que pode ser feito via fcntl , veja a resposta de Mark Plotnick).
Eu estava à beira da auto-resposta com dados empíricos quando escrevi a minha pergunta, e segui com uma auto-resposta, então aqui está como eu fiz:
no arquivo master.py
:
import subprocess
import logging
def main():
proc = ['python', 'parent.py']
logpath = 'parent.log'
with open(logpath, 'ab') as f:
p = subprocess.Popen(proc, stdout=f, stderr=subprocess.STDOUT)
logging.warn('task started, waiting to finish')
res = p.wait()
logging.warn(res)
if __name__ == '__main__':
main()
em parent.py
:
import os
import logging
def main():
proc = ['python', 'child.py']
logging.warn('parent is logging, pid: {0}'.format(os.getpid()))
os.execvp(proc[0], proc)
if __name__ == '__main__':
main()
e em child.py
:
import os
import logging
import time
def main():
for i in range(2):
logging.warn('child is logging, pid: {0}'.format(os.getpid()))
time.sleep(15)
if __name__ == '__main__':
main()
Quando eu executo python master.py
na linha de comando, a linha de comando gera isto:
WARNING:root:task started, waiting to finish
e cerca de 15 segundos depois:
WARNING:root:0
e o arquivo parent.log contém isto:
WARNING:root:parent is logging, pid 8515
WARNING:root:child is logging, pid 8515
WARNING:root:child is logging, pid 8515
que demonstra empiricamente que o filho herda os pipes junto com o pid do pai ao usar a família exec de funções. Foi difícil encontrar documentação de suporte sobre isso, mas há um exemplo fornecido aqui (mais ou menos na metade do material.)