|
1 """Spawn a command with pipes to its stdin, stdout, and optionally stderr. |
|
2 |
|
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. |
|
7 """ |
|
8 |
|
9 import os |
|
10 import sys |
|
11 import warnings |
|
12 warnings.warn("The popen2 module is deprecated. Use the subprocess module.", |
|
13 DeprecationWarning, stacklevel=2) |
|
14 |
|
15 __all__ = ["popen2", "popen3", "popen4"] |
|
16 |
|
17 try: |
|
18 MAXFD = os.sysconf('SC_OPEN_MAX') |
|
19 except (AttributeError, ValueError): |
|
20 MAXFD = 256 |
|
21 |
|
22 _active = [] |
|
23 |
|
24 def _cleanup(): |
|
25 for inst in _active[:]: |
|
26 if inst.poll(_deadstate=sys.maxint) >= 0: |
|
27 try: |
|
28 _active.remove(inst) |
|
29 except ValueError: |
|
30 # This can happen if two threads create a new Popen instance. |
|
31 # It's harmless that it was already removed, so ignore. |
|
32 pass |
|
33 |
|
34 class Popen3: |
|
35 """Class representing a child process. Normally, instances are created |
|
36 internally by the functions popen2() and popen3().""" |
|
37 |
|
38 sts = -1 # Child not completed yet |
|
39 |
|
40 def __init__(self, cmd, capturestderr=False, bufsize=-1): |
|
41 """The parameter 'cmd' is the shell command to execute in a |
|
42 sub-process. On UNIX, 'cmd' may be a sequence, in which case arguments |
|
43 will be passed directly to the program without shell intervention (as |
|
44 with os.spawnv()). If 'cmd' is a string it will be passed to the shell |
|
45 (as with os.system()). The 'capturestderr' flag, if true, specifies |
|
46 that the object should capture standard error output of the child |
|
47 process. The default is false. If the 'bufsize' parameter is |
|
48 specified, it specifies the size of the I/O buffers to/from the child |
|
49 process.""" |
|
50 _cleanup() |
|
51 self.cmd = cmd |
|
52 p2cread, p2cwrite = os.pipe() |
|
53 c2pread, c2pwrite = os.pipe() |
|
54 if capturestderr: |
|
55 errout, errin = os.pipe() |
|
56 self.pid = os.fork() |
|
57 if self.pid == 0: |
|
58 # Child |
|
59 os.dup2(p2cread, 0) |
|
60 os.dup2(c2pwrite, 1) |
|
61 if capturestderr: |
|
62 os.dup2(errin, 2) |
|
63 self._run_child(cmd) |
|
64 os.close(p2cread) |
|
65 self.tochild = os.fdopen(p2cwrite, 'w', bufsize) |
|
66 os.close(c2pwrite) |
|
67 self.fromchild = os.fdopen(c2pread, 'r', bufsize) |
|
68 if capturestderr: |
|
69 os.close(errin) |
|
70 self.childerr = os.fdopen(errout, 'r', bufsize) |
|
71 else: |
|
72 self.childerr = None |
|
73 |
|
74 def __del__(self): |
|
75 # In case the child hasn't been waited on, check if it's done. |
|
76 self.poll(_deadstate=sys.maxint) |
|
77 if self.sts < 0: |
|
78 if _active is not None: |
|
79 # Child is still running, keep us alive until we can wait on it. |
|
80 _active.append(self) |
|
81 |
|
82 def _run_child(self, cmd): |
|
83 if isinstance(cmd, basestring): |
|
84 cmd = ['/bin/sh', '-c', cmd] |
|
85 os.closerange(3, MAXFD) |
|
86 try: |
|
87 os.execvp(cmd[0], cmd) |
|
88 finally: |
|
89 os._exit(1) |
|
90 |
|
91 def poll(self, _deadstate=None): |
|
92 """Return the exit status of the child process if it has finished, |
|
93 or -1 if it hasn't finished yet.""" |
|
94 if self.sts < 0: |
|
95 try: |
|
96 pid, sts = os.waitpid(self.pid, os.WNOHANG) |
|
97 # pid will be 0 if self.pid hasn't terminated |
|
98 if pid == self.pid: |
|
99 self.sts = sts |
|
100 except os.error: |
|
101 if _deadstate is not None: |
|
102 self.sts = _deadstate |
|
103 return self.sts |
|
104 |
|
105 def wait(self): |
|
106 """Wait for and return the exit status of the child process.""" |
|
107 if self.sts < 0: |
|
108 pid, sts = os.waitpid(self.pid, 0) |
|
109 # This used to be a test, but it is believed to be |
|
110 # always true, so I changed it to an assertion - mvl |
|
111 assert pid == self.pid |
|
112 self.sts = sts |
|
113 return self.sts |
|
114 |
|
115 |
|
116 class Popen4(Popen3): |
|
117 childerr = None |
|
118 |
|
119 def __init__(self, cmd, bufsize=-1): |
|
120 _cleanup() |
|
121 self.cmd = cmd |
|
122 p2cread, p2cwrite = os.pipe() |
|
123 c2pread, c2pwrite = os.pipe() |
|
124 self.pid = os.fork() |
|
125 if self.pid == 0: |
|
126 # Child |
|
127 os.dup2(p2cread, 0) |
|
128 os.dup2(c2pwrite, 1) |
|
129 os.dup2(c2pwrite, 2) |
|
130 self._run_child(cmd) |
|
131 os.close(p2cread) |
|
132 self.tochild = os.fdopen(p2cwrite, 'w', bufsize) |
|
133 os.close(c2pwrite) |
|
134 self.fromchild = os.fdopen(c2pread, 'r', bufsize) |
|
135 |
|
136 |
|
137 if sys.platform[:3] == "win" or sys.platform == "os2emx": |
|
138 # Some things don't make sense on non-Unix platforms. |
|
139 del Popen3, Popen4 |
|
140 |
|
141 def popen2(cmd, bufsize=-1, mode='t'): |
|
142 """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may |
|
143 be a sequence, in which case arguments will be passed directly to the |
|
144 program without shell intervention (as with os.spawnv()). If 'cmd' is a |
|
145 string it will be passed to the shell (as with os.system()). If |
|
146 'bufsize' is specified, it sets the buffer size for the I/O pipes. The |
|
147 file objects (child_stdout, child_stdin) are returned.""" |
|
148 w, r = os.popen2(cmd, mode, bufsize) |
|
149 return r, w |
|
150 |
|
151 def popen3(cmd, bufsize=-1, mode='t'): |
|
152 """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may |
|
153 be a sequence, in which case arguments will be passed directly to the |
|
154 program without shell intervention (as with os.spawnv()). If 'cmd' is a |
|
155 string it will be passed to the shell (as with os.system()). If |
|
156 'bufsize' is specified, it sets the buffer size for the I/O pipes. The |
|
157 file objects (child_stdout, child_stdin, child_stderr) are returned.""" |
|
158 w, r, e = os.popen3(cmd, mode, bufsize) |
|
159 return r, w, e |
|
160 |
|
161 def popen4(cmd, bufsize=-1, mode='t'): |
|
162 """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may |
|
163 be a sequence, in which case arguments will be passed directly to the |
|
164 program without shell intervention (as with os.spawnv()). If 'cmd' is a |
|
165 string it will be passed to the shell (as with os.system()). If |
|
166 'bufsize' is specified, it sets the buffer size for the I/O pipes. The |
|
167 file objects (child_stdout_stderr, child_stdin) are returned.""" |
|
168 w, r = os.popen4(cmd, mode, bufsize) |
|
169 return r, w |
|
170 else: |
|
171 def popen2(cmd, bufsize=-1, mode='t'): |
|
172 """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may |
|
173 be a sequence, in which case arguments will be passed directly to the |
|
174 program without shell intervention (as with os.spawnv()). If 'cmd' is a |
|
175 string it will be passed to the shell (as with os.system()). If |
|
176 'bufsize' is specified, it sets the buffer size for the I/O pipes. The |
|
177 file objects (child_stdout, child_stdin) are returned.""" |
|
178 inst = Popen3(cmd, False, bufsize) |
|
179 return inst.fromchild, inst.tochild |
|
180 |
|
181 def popen3(cmd, bufsize=-1, mode='t'): |
|
182 """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may |
|
183 be a sequence, in which case arguments will be passed directly to the |
|
184 program without shell intervention (as with os.spawnv()). If 'cmd' is a |
|
185 string it will be passed to the shell (as with os.system()). If |
|
186 'bufsize' is specified, it sets the buffer size for the I/O pipes. The |
|
187 file objects (child_stdout, child_stdin, child_stderr) are returned.""" |
|
188 inst = Popen3(cmd, True, bufsize) |
|
189 return inst.fromchild, inst.tochild, inst.childerr |
|
190 |
|
191 def popen4(cmd, bufsize=-1, mode='t'): |
|
192 """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may |
|
193 be a sequence, in which case arguments will be passed directly to the |
|
194 program without shell intervention (as with os.spawnv()). If 'cmd' is a |
|
195 string it will be passed to the shell (as with os.system()). If |
|
196 'bufsize' is specified, it sets the buffer size for the I/O pipes. The |
|
197 file objects (child_stdout_stderr, child_stdin) are returned.""" |
|
198 inst = Popen4(cmd, bufsize) |
|
199 return inst.fromchild, inst.tochild |
|
200 |
|
201 __all__.extend(["Popen3", "Popen4"]) |