我最近需要编写一个执行的 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可能会在某处发生有 - 但你并不需要关心

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top