使用 os.pipe 和 os.fork() 问题的 Python 程序

标签 python pipe fork

我最近需要编写一个脚本来执行 os.fork() 以拆分为两个进程。子进程成为服务器进程,并使用由 os.pipe() 创建的管道将数据传回父进程。像往常一样,子项关闭管道的 'r' 端,父项关闭管道的 'w' 端。我使用 os.fdopen 将 pipe() 的返回值转换为文件对象。

我遇到的问题是:进程成功 fork ,子进程成为服务器。一切正常, child 尽职尽责地将数据写入管道的开放 'w' 端。不幸的是,管道的父端做了两件奇怪的事情:
A) 它阻塞在管道的 'r' 端的 read() 操作。
其次,它无法读取任何放在管道上的数据,除非 'w' 端完全关闭。

我立即认为缓冲是问题所在,并添加了 pipe.flush() 调用,但这些都没有帮助。

任何人都可以阐明为什么在写入端完全关闭之前数据不会出现吗?是否有使 read() 调用非阻塞的策略?

这是我的第一个 fork 或使用管道的 Python 程序,如果我犯了一个简单的错误,请原谅我。

最佳答案

您是在未指定大小的情况下使用 read(),还是将管道视为迭代器(for line in f)?如果是这样,那可能是问题的根源 - read() 被定义为在返回之前一直读取到文件末尾,而不是只读取可供读取的内容。这意味着它将阻塞,直到 child 调用 close()。

在链接到的示例代码中,这是可以的 - 父级以阻塞方式运行,并且仅将子级用于隔离目的。如果你想继续,那么要么像你发布的代码那样使用非阻塞 IO(但要准备好处理半完整的数据),要么分 block 读取(例如 r.read(size) 或 r.readline() ) 只会在读取特定大小/行之前阻塞。 (您仍然需要对 child 调用 flush)

看起来将管道视为迭代器也在使用一些进一步的缓冲区,因为“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)

关于使用 os.pipe 和 os.fork() 问题的 Python 程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/871447/

相关文章:

python - 使用 PyPlot 绘制平滑线

C - 从单亲 fork

c - 在并行环境中使用 fork、exec 和管道时出现死锁

c - Socketpair 仅打印 stdin 中的第一行

python - 使用带有 kind ='reg' 的 seabornpairplot 时出现轴限制问题

python - 用 Python 编写 OAuth 提供程序 : guide + libraries?

python - 如何将cherrypy.session()存储在变量中?

ruby - RSpec 管道破裂

pipe - 与多个 child 沟通的僵局

bash - 使用 curl 下载文件并通过 sha1sum 将其通过管道传输到 tar