error using pipes in python using os.pipe() and using os.fork()
Question:
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.
Answers:
Re-assigning r = os.fdopen(r)
is problematic here because the return value of os.fdopen
is a TextIOWrapper
, while the functions that use r
require the value to be an integer. The first time you run the loop it works just fine because r
is assigned to the first return from os.pipe()
, however, then on it’s converted to the TextIOWrapper
where it will fail for both os.fdopen()
and os.close()
Also, depending on the return value of r.read()
, it’s possible to get a None
value, causing the program to fail when you try to run number = int(number)
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
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.
Re-assigning r = os.fdopen(r)
is problematic here because the return value of os.fdopen
is a TextIOWrapper
, while the functions that use r
require the value to be an integer. The first time you run the loop it works just fine because r
is assigned to the first return from os.pipe()
, however, then on it’s converted to the TextIOWrapper
where it will fail for both os.fdopen()
and os.close()
Also, depending on the return value of r.read()
, it’s possible to get a None
value, causing the program to fail when you try to run number = int(number)
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