我有一些使用子进程模块运行的命令。然后我想循环遍历输出的每一行。文档中说不要使用data_stream.stdout.read,虽然我没有使用它,但可能会调用类似的命令。我是这样循环输出的:
for line in data_stream.stdout:
#do stuff here
.
.
.
像从data_stream.stdout读取数据那样循环,会导致死锁吗?还是Popen模块设置了这种类型的循环,使其使用通信代码但为您处理所有调用?
我有一些使用子进程模块运行的命令。然后我想循环遍历输出的每一行。文档中说不要使用data_stream.stdout.read,虽然我没有使用它,但可能会调用类似的命令。我是这样循环输出的:
for line in data_stream.stdout:
#do stuff here
.
.
.
像从data_stream.stdout读取数据那样循环,会导致死锁吗?还是Popen模块设置了这种类型的循环,使其使用通信代码但为您处理所有调用?
如果你在与子进程进行通信,即在写入stdin并从stdout读取时,你必须担心死锁问题。因为这些管道可能会被缓存,所以进行这种双向通信是非常不可取的:
data_stream = Popen(mycmd, stdin=PIPE, stdout=PIPE)
data_stream.stdin.write("do something\n")
for line in data_stream:
... # BAD!
然而,如果在构建数据流时没有设置stdin(或stderr),那么您应该没问题。
data_stream = Popen(mycmd, stdout=PIPE)
for line in data_stream.stdout:
... # Fine
实际上,这就是communicate()的工作原理;使用自己的线程的优点在于,您可以在生成时处理子进程的输出。例如,在我的项目python-gnupg
中,我使用此技术来读取GnuPG可执行文件生成的状态输出,而不是通过调用communicate()等待所有输出。您可以检查此项目的源代码 - 相关内容位于模块gnupg.py中。
data_stream.stdout
是一个标准输出句柄。您不应该循环遍历它。communicate
返回元组(stdoutdata,stderr)
。 您应该使用这个stdoutdata
来完成您的任务。
communicate
的说明是:“读取的数据被缓存在内存中,因此如果数据大小很大或无限制,请勿使用此方法。” - Alex Martelli