对于 perl 的包装器,我需要 python 中的非阻塞子进程(有各种类型的 shell io)。此外,我对 shell 输出和返回值感兴趣。有时返回值为 0,但代码实际上并没有做任何事情。
所以我现在可以使用 subprocess.call() (非阻塞但不是 shell 输出)或 subprocess.Popen() (阻塞但 shell 输出)。
我做了一些阅读,但唯一的解决方案似乎是有一个单独的队列来执行此操作。我错过了更容易的事情吗?
对于 perl 的包装器,我需要 python 中的非阻塞子进程(有各种类型的 shell io)。此外,我对 shell 输出和返回值感兴趣。有时返回值为 0,但代码实际上并没有做任何事情。
所以我现在可以使用 subprocess.call() (非阻塞但不是 shell 输出)或 subprocess.Popen() (阻塞但 shell 输出)。
我做了一些阅读,但唯一的解决方案似乎是有一个单独的队列来执行此操作。我错过了更容易的事情吗?
subprocess.Popen
并不是天生的阻塞。您仍然可以使用proc.stdin.write()
and 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
作为子进程运行,并将大量数据写入其标准输入。 cat
会将数据写入它自己的标准输出,直到它填满,然后它会阻塞,直到你的程序从标准输出读取一些数据并清空管道。但是您的程序仍在写入标准输入,并且cat
不再从中读取,因此管道也会填满。两个进程都将被阻塞写入,等待另一个读取,这永远不会发生。