On this page
17.5. popen2 —具有可访问的 I/O 流的子进程
从 2.6 版开始不推荐使用:该模块已淘汰。使用subprocess模块。尤其要检查用子流程模块替换旧Function部分。
该模块允许您生成进程并连接到它们的 Importing/输出/错误管道,并在 Unix 和 Windows 下获取它们的返回码。
subprocess模块提供了更强大的Function来生成新流程并检索其结果。使用subprocess模块比使用popen2模块更好。
此模块提供的主要接口是工厂Function的三个。对于每一个,如果指定* bufsize *,它将为 I/O 管道指定缓冲区大小。 * mode *(如果提供)应为字符串'b'
或't'
;在 Windows 上,这需要确定是应以二进制还是文本模式打开文件对象。 * mode *的默认值为't'
。
在 Unix 上,* cmd 可能是一个序列,在这种情况下,参数将直接传递给程序,而无需 shell 干预(例如os.spawnv())。如果 cmd *是字符串,它将被传递到 Shell 程序(与os.system()一样)。
检索子进程的返回码的唯一方法是使用Popen3和Popen4类上的poll()
或wait()
方法。这些仅在 Unix 上可用。当使用popen2(),popen3()和popen4()Function或os模块中的等效Function时,此信息不可用。 (请注意,os模块的函数返回的 Tuples 的 Sequences 与popen2模块的返回 Tuples 的 Sequences 不同。)
popen2.
popen2
(* cmd * [,* bufsize * [,* mode *]])- 将* cmd *作为 subprocess 执行。返回文件对象
(child_stdout, child_stdin)
。
- 将* cmd *作为 subprocess 执行。返回文件对象
popen2.
popen3
(* cmd * [,* bufsize * [,* mode *]])- 将* cmd *作为 subprocess 执行。返回文件对象
(child_stdout, child_stdin, child_stderr)
。
- 将* cmd *作为 subprocess 执行。返回文件对象
popen2.
popen4
(* cmd * [,* bufsize * [,* mode *]])- 将* cmd *作为 subprocess 执行。返回文件对象
(child_stdout_and_stderr, child_stdin)
。
- 将* cmd *作为 subprocess 执行。返回文件对象
2.0 版中的新Function。
在 Unix 上,还可以使用定义工厂函数返回的对象的类。这些未用于 Windows 实施,并且在该平台上不可用。
-
- class *
popen2.
Popen3
(* cmd * [,* capturestderr * [,* bufsize *]])
- class *
如果未使用辅助函数之一创建Popen3对象,则参数* cmd *是要在子进程中执行的 shell 命令。 * capturestderr 标志,如果为 true,则指定对象应捕获子进程的标准错误输出。默认为 false。如果指定了 bufsize *参数,则它指定往返于子进程的 I/O 缓冲区的大小。
-
- class *
popen2.
Popen4
(* cmd * [,* bufsize *])
- class *
2.0 版中的新Function。
17.5.1. Popen3 和 Popen4 对象
Popen3.
poll
( )- 如果子进程尚未完成,则返回
-1
,否则返回其状态码(请参见wait())。
- 如果子进程尚未完成,则返回
Popen3.
wait
( )- await 并返回子进程的状态码。状态码既对进程的返回码进行编码,又对有关使用
exit()
系统调用退出还是由于 signal 死亡的信息进行编码。 os模块中定义了帮助解释状态代码的Function;有关W*()
系列Function,请参见Process Management部分。
- await 并返回子进程的状态码。状态码既对进程的返回码进行编码,又对有关使用
以下属性也可用:
Popen3.
fromchild
- 提供子进程输出的文件对象。对于Popen4实例,这将提供标准输出和标准错误流。
Popen3.
tochild
- 为子进程提供 Importing 的文件对象。
Popen3.
childerr
- 如果* capturestderr *对于构造函数为 true,则该文件对象提供子进程的错误输出,否则为
None
。对于Popen4个实例,该值始终为None
。
- 如果* capturestderr *对于构造函数为 true,则该文件对象提供子进程的错误输出,否则为
Popen3.
pid
- 子进程的进程 ID。
17.5.2. 流控制问题
任何时候使用任何形式的进程间通信,都需要仔细考虑控制流程。此模块提供的文件对象(或os模块等效项)仍然如此。
当父进程正在从子进程的标准输出中读取数据时,如果从子进程读取将大量数据写入标准错误的输出,则会发生死锁。其他读写组合也会发生类似情况。重要因素是,一个进程正在以阻塞方式写入多个_PC_PIPE_BUF
字节,而另一个进程也在以阻塞方式从第一个进程读取数据。
有几种方法可以处理这种情况。
在许多情况下,最简单的应用程序更改是在父流程中遵循此模型:
import popen2
r, w, e = popen2.popen3('python slave.py')
e.readlines()
r.readlines()
r.close()
e.close()
w.close()
在子代码中带有以下代码:
import os
import sys
# note that each of these print statements
# writes a single long string
print >>sys.stderr, 400 * 'this is a test\n'
os.close(sys.stderr.fileno())
print >>sys.stdout, 400 * 'this is another test\n'
特别要注意的是,写入所有数据后必须关闭sys.stderr
,否则readlines()
将不会返回。另请注意,必须使用os.close(),因为sys.stderr.close()
不会关闭stderr
(否则,分配给sys.stderr
会以静默方式关闭stderr
,因此无法再打印任何错误)。
需要支持更通用方法的应用程序应将管道上的 I/O 与它们的select()循环集成在一起,或使用单独的线程读取使用popen*()
函数或Popen*
类提供的每个单独文件。
See also
Module subprocess
用于产生和 Management 子流程的模块。