python中的非阻塞子进程

时间:2013-02-17 19:06:50

标签: python-2.7 subprocess nonblocking tcsh

对于perl的包装我需要python中的非阻塞子进程(有各种类型的shell io)。另外,我对shell输出和返回值感兴趣。有时返回值为0,但代码实际上并没有做任何事情 所以我现在可以使用subprocess.call()(非阻塞但不是shell输出)或subprocess.Popen()(阻塞但是shell输出)。

我做了一些阅读,但唯一的解决方案看起来像是有一个单独的队列来做这件事。我错过了哪一个更容易?

1 个答案:

答案 0 :(得分:4)

subprocess.Popen本身并不是阻止。您仍然可以使用proc.stdin.write()proc.stdout.read();唯一的问题是,如果管道填满,你可能会在一侧发生阻塞,甚至死锁[1]。如果您知道您的子进程只会读取或写入少量数据,则不必担心。

所以你可以这样做:

proc = subprocess.Popen(['perl', 'somescript.pl'], stdout=subprocess.PIPE)
buf = StringIO()
CHUNKSIZE = 1024  # how much to read at a time

while True:
    # do whatever other time-consuming work you want here, including monitoring
    # other processes...


    # this keeps the pipe from filling up
    buf.write(proc.stdout.read(CHUNKSIZE))

    proc.poll()
    if proc.returncode is not None:
        # process has finished running
        buf.write(proc.stdout.read())
        print "return code is", proc.returncode
        print "output is", buf.getvalue()

        break

在较大的应用程序中,您可以在事件循环,反应堆等中安排此操作。


[1]操作系统一次只允许这么多数据放入管道中。假设您运行cat作为您的子进程,并将大量数据写入其stdin。 cat会将该数据写入其自己的标准输出,直到它填满为止,然后它将阻塞,直到您的程序从stdout读取一些数据并清空管道。但是你的程序仍在写入stdin,cat不再读取它,因此管道也会填满。这两个进程都会遇到阻塞写入,等待另一个进程读取,这将永远不会发生。