3

在使用 Pythonsubprocess库生成子进程后,我使用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。

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

4

2 回答 2

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
于 2011-07-14T21:41:55.670 回答
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

于 2011-07-14T21:51:58.203 回答