-5

我正在尝试用python编写一个程序,通过父函数将2个整数写入管道,然后通过子函数读取这些相同的整数。然后子函数应该打印出两者的乘积。

问题是,当我运行它时,它会像预期的那样等待 5 秒,然后返回值 441 而不是 2。

希望有人可以帮助弄清楚如何修复此代码:)

import os,time

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

def parent():
    pipein,pipeout = os.pipe()
    x=5
    if os.fork()==0:
        child(pipein)
    else:
        while True:
            num1=str(2)
            num2=str(1)
            line=os.write(pipeout,num1.encode())
            line=os.write(pipeout,num2.encode())
            time.sleep(x)   

parent()
4

2 回答 2

0

最直接的问题是你的孩子有一个无限循环,num1在做任何事情之前,他会一遍又一遍地阅读(或者,更确切地说,阅读两次,然后在永远不会出现的第三个输入上永远阻塞)。

通过将更多代码移动到while循环中来解决此问题,如下所示:

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

而且您也可以删除os._exit(0),因为无论如何您都无法达到它。


您的下一个问题是您的编码和解码步骤不匹配。只要你sys.getdefaultencoding()的东西是 ASCII 的严格超集(或者,真的,只要它的数字与 ASCII 数字匹配),你就可以摆脱这个问题,但你真的不应该默默地依赖它。


接下来,os.read(pipein,32)可以为您提供单次写入的结果,也可以为您提供最多 32 次单独写入组合在一起的结果。保证(最多 PIPE_BUF)是原子的这一事实对write您没有帮助 - 它只是意味着您不能以写入的前半部分而不是后半部分结束。

所以,最有可能的是,你会得到21in num1,然后 5 秒后得到另一个21in num2,所以不是2每 5 秒打印一次,而是441每 10 秒打印一次。但即使这样也不能保证。

管道和 TCP 套接字一样,是字节流,而不是消息流。这意味着您需要构建某种协议。


这里有两个非常明显的选择。

首先,既然您已经在读取(最多)32 字节的固定记录大小,为什么不写入正好为 32 字节的固定记录大小呢?只需将您的str行更改为生成正好为 32 个字符的字符串的内容,该字符串将在任何已经有效的编码中编码为 32 个字节,并将解析为适当值的单个整数。像这样:

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

或者,每条记录可以是一对以空格分隔的数字,并且可以用换行符分隔记录。这很容易解析。特别是因为您没有使用非阻塞管道或任何东西,所以您可以在它们周围放置一个文件对象并使其变得容易。

于 2013-10-30T19:29:49.483 回答
-1

这就是我的想法;

from __future__ import print_function  #(1)
import os  #(2)
import sys
import time


def child(pipein):  # (3)
    num1 = int(os.read(pipein, 32))  # (6)
    num2 = int(os.read(pipein, 32))
    r = num1 * num2
    print("r = {}".format(r))
    print("Child says bye.") 
    sys.stdout.flush()  # (4)
    os._exit(0)  # (5)


def parent():
    pipein, pipeout = os.pipe()
    x = 1
    if os.fork() == 0:
        print("Launching child")
        child(pipein)
    else:  # (7)
        print("In parent")
        num1 = str(2)  # (8)
        num2 = str(1)
        os.write(pipeout, num1)
        os.write(pipeout, num2)
        print("Parent goes to sleep")
        time.sleep(x)
        print("Parent says bye.")


if __name__ == '__main__':
    parent()
  1. 这是使print() 函数在 Python 2.x 中工作所必需的
  2. 样式:每个导入都应该在单独的行上
  3. exit()如果您要在第一次迭代后进行循环,则无需循环
  4. 否则打印可能不会显示。
  5. 样式:在函数后使用两个空行。
  6. 样式:在逗号后使用空格,除非它位于行尾。
  7. 删除 while 循环,否则您将处于无限循环中。
  8. 样式:在运算符周围使用空格。

通过这些修改,我得到以下输出;

In parent
Launching child
Parent goes to sleep
r = 2
Child says bye.
Parent says bye.

multiprocessing如果你想使用多个进程,使用模块通常是一个更好的主意。它具有进程和进程池的对象,以及队列和管道等通信对象。队列是先进先出的,并且是同步的;因此,如果您放入两个项目,则可以读取两个项目。

于 2013-10-30T19:55:22.277 回答