python中的管道和分叉

2024-09-28 17:27:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用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()

Tags: 函数childtruereadtimeosdef整数
2条回答

直接的问题是,您的孩子有一个无限循环,在做任何事情之前总是反复地读取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个单独写入组合在一起的结果。保证write(最多为PIPE_BUF)是原子的这一事实并不能帮助您,它只是意味着您不能结束前半部分的写入,而不是下半部分。在

所以,最有可能的是,你将在num1中得到21,然后5秒钟后在num2中得到另一个{},因此,不是每5秒打印一次{},而是每10秒打印一次{}。但即便如此也不能保证。在

管道和TCP套接字一样是byte streams, not message streams。这意味着你需要建立某种协议。在


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

既然32字节大小的记录已经被修正了,那为什么不写一个32字节的记录呢?只需将str行更改为生成一个正好由32个字符组成的字符串,该字符串将在任何已生效的编码中被编码为32个字节,并将解析为适当值的单个整数。像这样:

^{pr2}$

或者,每个记录可以是一对空格分隔的数字,记录可以用换行符分隔。分析起来很简单。尤其是因为您不使用非阻塞管道或任何东西,所以您只需在管道周围放置一个文件对象就可以了。在

这就是我对它的理解

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()函数在python2.x中工作所必需的
  2. 风格:导入应该在单独的行上
  3. 如果要在第一次迭代之后exit(),则不需要循环
  4. 否则指纹可能不会出现。在
  5. 样式:在函数后使用两个空行。在
  6. 除非在行尾使用逗号。在
  7. 删除while循环,否则将处于无限循环中。在
  8. 样式:在运算符周围使用空格。在

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

^{pr2}$

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

相关问题 更多 >