Piping and forking in python

The immediate problem is that your child has an infinite loop, reading num1 over and over forever (or, rather, reading it twice and then blocking forever on a third input that will never come) before doing anything.

Fix that by moving more of the code into the while loop, like this:

def child(pipein):
    while True:
        num1 = int(os.read(pipein,32))
        num2 = int(os.read(pipein,32))
        r=(num1)*(num2)
        print(r)

And you might as well remove the os._exit(0), because you’re never going to reach it anyway.


Your next problem is that your encoding and decoding steps don’t match. You’ll get away with this as long as your sys.getdefaultencoding() is something that’s a strict superset of ASCII (or, really, as long as its digits match ASCII digits), but you really shouldn’t silently rely on that.


Next, os.read(pipein,32) can give you the results of a single write, or it can give you the results of up to 32 separate writes combined together. The fact that write (of up to PIPE_BUF) is guaranteed be atomic doesn’t help you—it just means you can’t end up with the first half of a write and not the second half.

So, most likely, you’ll get the 21 in num1, and then 5 seconds later get another 21 in num2, so instead of printing out 2 every 5 seconds, you’ll print out 441 every 10 seconds. But even that isn’t guaranteed.

Pipes, like TCP sockets, are byte streams, not message streams. Which means you need to build some kind of protocol.


There are two really obvious choices here.

First, since you’re already reading a fixed record size of (up to) 32 bytes, why not write a fixed record size of exactly 32 bytes? Just change your str lines to something that generates a string of exactly 32 characters that will be encoded to 32 bytes in any encoding that already works, and will parse as a single integer of the appropriate value. Like this:

num1 = format(2, '32d')
num2 = format(1, '32d')

Alternatively, each record can be a pair of whitespace-separated numbers, and records can be separated with newlines. That’s trivial to parse. Especially since you’re not using non-blocking pipes or anything, so you can just put a file object around them and make it all easy.

Leave a Comment