在stdout / stderr文件描述符上调用os.fsync会终止子进程

时间:2011-07-14 21:26:16

标签: python subprocess fsync

使用Python subprocess库生成子进程后,我使用stderr将子进程的消息传递给包含一些序列化数据的父进程。然后,我希望父级返回(通过stdin)应用于此数据的函数的结果。

本质上,我在子进程中有一个函数,它执行如下操作:

sys.stderr.write("some stuff to write")
# some time later
some_var = sys.stdin.read()

但是,这样就完成了在等待stderr输入时锁定父节点,所以我试着调用:

sys.stderr.flush()
os.fsync(sys.stderr.fileno())

然而,这不起作用。 os.fsync执行后没有任何内容。此外,当我在父进程中调用proc.poll()时,显示该子进程的返回码为1.

我该怎么做才能防止这种情况发生?我应该考虑另一种方法吗?

2 个答案:

答案 0 :(得分:2)

我会考虑另一种方法。 您可以使用独立进程(multiprocessing.Process)并使用两个队列与其进行通信(multiprocessing.Queue),一个用于输入,另一个用于输出。 启动流程的示例:

import multiprocessing

def processWorker(input, result):
    work = input.get()
    print work
    result.put(work*work)

input  = multiprocessing.Queue()
result = multiprocessing.Queue()

p = multiprocessing.Process(target = processWorker, args = (input, result))
p.start()

input.put(2)
res = result.get(block = True)
print res

然后你可以再次迭代传递它。使用multiprocessing.Queue更加健壮,因为您不需要依赖stdout / err解析,也可以避免相关限制。 此外,您可以轻松管理更多子流程。

然后,您还可以设置您希望get调用等待多长时间的超时,例如:

import queue
try:
    res = result.get(block = True, timeout = 10)
except Queue.Empty:
    print error

答案 1 :(得分:1)

以下是如何在不彻底改变方法的情况下防止I / O死锁的方法。在孩子身上:

import os, fcntl
map(lambda f: fcntl.fcntl(f.fileno(), fcntl.F_SETFL, os.O_NONBLOCK),
    (sys.stdin, sys.stdout, sys.stderr))

在父级中,对子级的管道文件描述符执行相同操作。然后,当您使用select.select()进行通信时,您将不再拥有这些锁定。但是,您必须在写入之前使用select(),在尝试读/写时可能会收到EAGAIN错误,并且根据您的应用程序逻辑,您可能无论如何都会有无限期的等待情况。

老实说,我建议您查看Twisted框架,该框架内置了子进程功能:http://twistedmatrix.com/documents/current/core/howto/process.html