pythonprocesspipeoserror

error using pipes in python using os.pipe() and using os.fork()


So I made a simple piece of code to add 1 to a value. I create two process and I am creating a pipe for storage the information beetween iterations. In the first cycle it gives the correct value but in the second iterration it gives two errors. My code:

def processMain():
    number = 0
    r, w = os.pipe()

    for _ in range(2):
        pid = os.fork()
        if pid == 0:
            number = int(number)
            number += 1
            number = str(number)

            os.close(r)
            w = os.fdopen(w, "w")
            w.write(number)
            print("write")
            sys.exit(0)

        else:
            os.wait()

            os.close(w)
            r = os.fdopen(r)
            number = r.read()
            print("read")
    print(number)

I excute the function and it gives me this results:

write
read
Traceback (most recent call last):
  File "/home/aluno-di/area-de-aluno/SO/projeto/grupoXX/tests.py", line 31, in <module>
    processMain()
  File "/home/aluno-di/area-de-aluno/SO/projeto/grupoXX/tests.py", line 15, in processMain
    os.close(r)
TypeError: '_io.TextIOWrapper' object cannot be interpreted as an integer
Traceback (most recent call last):
  File "/home/aluno-di/area-de-aluno/SO/projeto/grupoXX/tests.py", line 31, in <module>
    processMain()
  File "/home/aluno-di/area-de-aluno/SO/projeto/grupoXX/tests.py", line 24, in processMain
    os.close(w)
OSError: [Errno 9] Bad file descriptor

I don't understand what I am doing wrong or what I am not doing that I need to do to this work.


Solution

  • This should work. Note that number needs to be a shared memory value if you want the incrementing done by the child process reflected in the main process:

    import os
    from multiprocessing import Value, Pipe
    import sys
    
    def processMain():
        number = Value('i', 0)
        r, w = Pipe(duplex=False)
    
        for _ in range(2):
            pid = os.fork()
            if pid == 0:
                number.value += 1
                n = number.value
                w.send(n)
                sys.exit(0)
            else:
                n = r.recv()
                print("read", n)
                os.waitid(os.P_PID, pid, os.WEXITED)
    
    processMain()
    

    Prints:

    read 1
    read 2