我正在尝试在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()
答案 0 :(得分: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)
,因为无论如何你永远都不会去。{/ p>
您的下一个问题是您的编码和解码步骤不匹配。只要你的sys.getdefaultencoding()
是ASCII的严格超集(或者,实际上,只要它的数字与ASCII数字匹配),你就可以逃脱这一点,但你真的不应该默默地依赖它。
接下来,os.read(pipein,32)
可以为您提供单次写入的结果,或者它可以为您提供最多32个单独写入组合在一起的结果。 write
(最高为PIPE_BUF)保证是原子的这一事实对你没有帮助 - 它只是意味着你不能以写入的前半部分而不是后半部分结束。
所以,很有可能,你会在21
中获得num1
,然后在5秒后获得21
中的另一个num2
,而不是打印{ {1}}每5秒钟,您将每10秒打印一次2
。但即使这样也无法保证。
管道,如TCP套接字,是byte streams, not message streams。这意味着您需要构建某种协议。
这里有两个非常明显的选择。
首先,由于您已经读取了(最多)32字节的固定记录大小,为什么不写一个完全32字节的固定记录大小?只需将441
行更改为生成正好为32个字符的字符串的字符串,该字符串将在已有效的任何编码中编码为32个字节,并将解析为适当值的单个整数。像这样:
str
或者,每条记录可以是一对以空格分隔的数字,记录可以用换行符分隔。解析这一点很简单。特别是因为你没有使用非阻塞管道或任何东西,所以你可以在它们周围放置一个文件对象并使它变得容易。
答案 1 :(得分:-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()
print()
函数在Python 2.x中工作所必需的exit()
,则无需循环通过这些修改,我得到以下输出;
In parent
Launching child
Parent goes to sleep
r = 2
Child says bye.
Parent says bye.
如果要使用多个进程,使用multiprocessing
模块通常会更好。它包含进程和进程池的对象,以及队列和管道等通信对象。队列是先进先出,并且它们是同步的;因此,如果您放入两个项目,则可以阅读两个项目。