1 """Spawn a command with pipes to its stdin, stdout, and optionally stderr.
3 The normal os.popen(cmd, mode) call spawns a shell command and provides a
4 file interface to just the input or output of the process depending on
5 whether mode is 'r' or 'w'. This module provides the functions popen2(cmd)
6 and popen3(cmd) which return two or three pipes to the spawned command.
12 __all__
= ["popen2", "popen3", "popen4"]
15 MAXFD
= os
.sysconf('SC_OPEN_MAX')
16 except (AttributeError, ValueError):
22 for inst
in _active
[:]:
26 """Class representing a child process. Normally instances are created
27 by the factory functions popen2() and popen3()."""
29 sts
= -1 # Child not completed yet
31 def __init__(self
, cmd
, capturestderr
=False, bufsize
=-1):
32 """The parameter 'cmd' is the shell command to execute in a
33 sub-process. On UNIX, 'cmd' may be a sequence, in which case arguments
34 will be passed directly to the program without shell intervention (as
35 with os.spawnv()). If 'cmd' is a string it will be passed to the shell
36 (as with os.system()). The 'capturestderr' flag, if true, specifies
37 that the object should capture standard error output of the child
38 process. The default is false. If the 'bufsize' parameter is
39 specified, it specifies the size of the I/O buffers to/from the child
42 p2cread
, p2cwrite
= os
.pipe()
43 c2pread
, c2pwrite
= os
.pipe()
45 errout
, errin
= os
.pipe()
55 self
.tochild
= os
.fdopen(p2cwrite
, 'w', bufsize
)
57 self
.fromchild
= os
.fdopen(c2pread
, 'r', bufsize
)
60 self
.childerr
= os
.fdopen(errout
, 'r', bufsize
)
65 def _run_child(self
, cmd
):
66 if isinstance(cmd
, basestring
):
67 cmd
= ['/bin/sh', '-c', cmd
]
68 for i
in range(3, MAXFD
):
74 os
.execvp(cmd
[0], cmd
)
79 """Return the exit status of the child process if it has finished,
80 or -1 if it hasn't finished yet."""
83 pid
, sts
= os
.waitpid(self
.pid
, os
.WNOHANG
)
92 """Wait for and return the exit status of the child process."""
94 pid
, sts
= os
.waitpid(self
.pid
, 0)
101 class Popen4(Popen3
):
104 def __init__(self
, cmd
, bufsize
=-1):
106 p2cread
, p2cwrite
= os
.pipe()
107 c2pread
, c2pwrite
= os
.pipe()
116 self
.tochild
= os
.fdopen(p2cwrite
, 'w', bufsize
)
118 self
.fromchild
= os
.fdopen(c2pread
, 'r', bufsize
)
122 if sys
.platform
[:3] == "win" or sys
.platform
== "os2emx":
123 # Some things don't make sense on non-Unix platforms.
126 def popen2(cmd
, bufsize
=-1, mode
='t'):
127 """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
128 be a sequence, in which case arguments will be passed directly to the
129 program without shell intervention (as with os.spawnv()). If 'cmd' is a
130 string it will be passed to the shell (as with os.system()). If
131 'bufsize' is specified, it sets the buffer size for the I/O pipes. The
132 file objects (child_stdout, child_stdin) are returned."""
133 w
, r
= os
.popen2(cmd
, mode
, bufsize
)
136 def popen3(cmd
, bufsize
=-1, mode
='t'):
137 """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
138 be a sequence, in which case arguments will be passed directly to the
139 program without shell intervention (as with os.spawnv()). If 'cmd' is a
140 string it will be passed to the shell (as with os.system()). If
141 'bufsize' is specified, it sets the buffer size for the I/O pipes. The
142 file objects (child_stdout, child_stdin, child_stderr) are returned."""
143 w
, r
, e
= os
.popen3(cmd
, mode
, bufsize
)
146 def popen4(cmd
, bufsize
=-1, mode
='t'):
147 """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
148 be a sequence, in which case arguments will be passed directly to the
149 program without shell intervention (as with os.spawnv()). If 'cmd' is a
150 string it will be passed to the shell (as with os.system()). If
151 'bufsize' is specified, it sets the buffer size for the I/O pipes. The
152 file objects (child_stdout_stderr, child_stdin) are returned."""
153 w
, r
= os
.popen4(cmd
, mode
, bufsize
)
156 def popen2(cmd
, bufsize
=-1, mode
='t'):
157 """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
158 be a sequence, in which case arguments will be passed directly to the
159 program without shell intervention (as with os.spawnv()). If 'cmd' is a
160 string it will be passed to the shell (as with os.system()). If
161 'bufsize' is specified, it sets the buffer size for the I/O pipes. The
162 file objects (child_stdout, child_stdin) are returned."""
163 inst
= Popen3(cmd
, False, bufsize
)
164 return inst
.fromchild
, inst
.tochild
166 def popen3(cmd
, bufsize
=-1, mode
='t'):
167 """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
168 be a sequence, in which case arguments will be passed directly to the
169 program without shell intervention (as with os.spawnv()). If 'cmd' is a
170 string it will be passed to the shell (as with os.system()). If
171 'bufsize' is specified, it sets the buffer size for the I/O pipes. The
172 file objects (child_stdout, child_stdin, child_stderr) are returned."""
173 inst
= Popen3(cmd
, True, bufsize
)
174 return inst
.fromchild
, inst
.tochild
, inst
.childerr
176 def popen4(cmd
, bufsize
=-1, mode
='t'):
177 """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
178 be a sequence, in which case arguments will be passed directly to the
179 program without shell intervention (as with os.spawnv()). If 'cmd' is a
180 string it will be passed to the shell (as with os.system()). If
181 'bufsize' is specified, it sets the buffer size for the I/O pipes. The
182 file objects (child_stdout_stderr, child_stdin) are returned."""
183 inst
= Popen4(cmd
, bufsize
)
184 return inst
.fromchild
, inst
.tochild
186 __all__
.extend(["Popen3", "Popen4"])
193 # "more" doesn't act the same way across Windows flavors,
194 # sometimes adding an extra newline at the start or the
195 # end. So we strip whitespace off both ends for comparison.
196 expected
= teststr
.strip()
197 print "testing popen2..."
202 if got
.strip() != expected
:
203 raise ValueError("wrote %r read %r" % (teststr
, got
))
204 print "testing popen3..."
206 r
, w
, e
= popen3([cmd
])
208 r
, w
, e
= popen3(cmd
)
212 if got
.strip() != expected
:
213 raise ValueError("wrote %r read %r" % (teststr
, got
))
216 raise ValueError("unexpected %r on stderr" % (got
,))
217 for inst
in _active
[:]:
220 raise ValueError("_active not empty")
223 if __name__
== '__main__':