I have a multiprocessing system, with a main process and two child ones.
One of the child processes (say, C1) sends messages to the other child (C2) through a Queue. C2 analyzes the messages from C1 and, when certain conditions occur, it requires some input from the user.
So, the situation looks like this:
main.py
from child_process_01 import Child_Process_01
from child_process_02 import Child_Process_02
set_start_method("spawn")
c1_c2_q = Queue(maxsize=1)
c1 = mp.Process(target=Child_Process_01, args=(c1_c2_q,))
c1.daemon = True
c1.start()
c2 = mp.Process(target=Child_Process_02, args=(c1_c2_q,))
c2.daemon = True
c2.start()
Child_Process_01
message = produced somehow
c1_c2_q.put((message))
Child_Process_02
## infinite loop, keep checking messages and ask for user input under certain conditions
while True:
try:
message = c1_c2_q.get_nowait()
except:
message = None
## when message arrives
if message:
if message = something:
usr_input = input('In this situation, I need user input')
The code doesn't work as it is, since the multiprocessing module closes the standard input of all processes it creates, as I found out in many answers here. A good suggestion seemed to redefine the standard in in the main process and to send it to the child, like explained here or here, so I tried it:
main.py
newstdin = os.fdopen(os.dup(sys.stdin.fileno()))
c2 = mp.Process(target=Child_Process_02, args=(c1_c2_q, newstdin))
c2.daemon = True
c2.start()
Child_Process_02
def Child_Process_02(c1_c2_q, newstdin):
sys.stdin = newstdin
while True:
try:
message = c1_c2_q.get_nowait()
except:
message = None
## when message arrives
if message:
if message = something:
usr_input = input('In this situation, I need user input')
but this doesn't work either, because I can't pass the newstdin object created in the main process through a queue, I get the error:
TypeError: cannot pickle '_io.TextIOWrapper' object
Moreover, a few comments to similar question discouraged the practice of reading input from child processes in general, but I can't imagine how to do it differently. Any suggestions?