使用os.pipe和os.fork Python程序()问题
题
我最近需要编写一个执行的 os.fork()以分成两个过程的脚本。子进程变为一个服务器进程并且使用的 os.pipe()与创建的管材通过的数据返回给父进程即可。孩子关闭管道的'r'
结束,父进程关闭管道的'w'
结束,一如往常。余转换从管()中的返回到文件中的对象是 os.fdopen 即可。
时遇到的问题是这样的:成功的方法叉,和孩子变成服务器。一切的伟大工程和孩子尽职尽责地将数据写入到管道的开放'w'
结束。不幸的是,管道的父结束做两件怪事:点击
A)上的配管的read()
端'r'
操作它的块。结果
其次,它无法读取已置于管道除非'w'
端完全关闭的任何数据。
我立刻想到,缓冲是问题,并添加 pipe.flush()电话,但这些并没有帮助。
任何人都可以阐明为什么数据没有出现,直到书写端的一些光完全关闭?并有使read()
通话无阻塞的策略?
这是我的那分叉或使用的管道,所以请原谅我,如果我做了一个简单的错误第一个Python程序。
解决方案
您使用而不指定大小,或处理管作为一个迭代(for line in f
)读()?如果是这样,这可能是你的问题的根源 - 阅读()被定义在返回前读到文件的末尾,而不是仅仅读什么是可以读取。这将意味着它会阻止,直到孩子调用close()。
在连接到示例代码,这是行 - 父充当在阻塞的方式,只是使用用于隔离目的的孩子。如果你想继续,然后要么使用非阻塞IO为您发布的代码(但要准备应付半完成数据),或大块(读如r.read(大小)或r.readline() ),直到一个特定的大小/线已被读取,这将只阻塞。 (你仍然需要调用子齐平)
它看起来像作为迭代器使用一些进一步的缓冲,以及,处理管道的“for line in r:
”可能不会给你想要的东西,如果你需要每行马上食用。它可能会禁用此,但只是在fdopen缓冲区大小指定0似乎并不足够。
下面有一些示例代码应工作:
import os, sys, time
r,w=os.pipe()
r,w=os.fdopen(r,'r',0), os.fdopen(w,'w',0)
pid = os.fork()
if pid: # Parent
w.close()
while 1:
data=r.readline()
if not data: break
print "parent read: " + data.strip()
else: # Child
r.close()
for i in range(10):
print >>w, "line %s" % i
w.flush()
time.sleep(1)
其他提示
使用
fcntl.fcntl(readPipe, fcntl.F_SETFL, os.O_NONBLOCK)
调用读()之前解决这两个问题。读出的()调用不再阻塞,只是冲洗()的写入结束之后的数据被显示。
我明白你已经解决了阻塞I / O和缓冲的问题。
如果你决定尝试一种不同的方法的说明:子是等效/拿叉/ EXEC成语的替代品。好像这是你做的不是:你刚才的两个进程之间的叉(不一个可执行程序)和交换数据 - 在这种情况下的 multiprocessing
模块(在Python 2.6+)将是更好的选择。
“父”与在Python应用叉的“子”部分是愚蠢的。这是从16位UNIX天的遗产。这是从一天的做作,当叉/ exec和EXEC是重要的事情要充分利用一个小小的处理器。
将您的Python代码分成两个独立的部分:父和子
父部分应使用子来运行子部分。
一个fork和exec可能会在某处发生有 - 但你并不需要关心
。