Vega strike Python Modules doc  0.5.1
Documentation of the " Modules " folder of Vega strike
 All Data Structures Namespaces Files Functions Variables
popen2.py
Go to the documentation of this file.
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 types
12 
13 __all__ = ["popen2", "popen3", "popen4"]
14 
15 MAXFD = 256 # Max number of file descriptors (os.getdtablesize()???)
16 
17 _active = []
18 
19 def _cleanup():
20  for inst in _active[:]:
21  inst.poll()
22 
23 class Popen3:
24  """Class representing a child process. Normally instances are created
25  by the factory functions popen2() and popen3()."""
26 
27  sts = -1 # Child not completed yet
28 
29  def __init__(self, cmd, capturestderr=0, bufsize=-1):
30  """The parameter 'cmd' is the shell command to execute in a
31  sub-process. The 'capturestderr' flag, if true, specifies that
32  the object should capture standard error output of the child process.
33  The default is false. If the 'bufsize' parameter is specified, it
34  specifies the size of the I/O buffers to/from the child process."""
35  _cleanup()
36  p2cread, p2cwrite = os.pipe()
37  c2pread, c2pwrite = os.pipe()
38  if capturestderr:
39  errout, errin = os.pipe()
40  self.pid = os.fork()
41  if self.pid == 0:
42  # Child
43  os.dup2(p2cread, 0)
44  os.dup2(c2pwrite, 1)
45  if capturestderr:
46  os.dup2(errin, 2)
47  self._run_child(cmd)
48  os.close(p2cread)
49  self.tochild = os.fdopen(p2cwrite, 'w', bufsize)
50  os.close(c2pwrite)
51  self.fromchild = os.fdopen(c2pread, 'r', bufsize)
52  if capturestderr:
53  os.close(errin)
54  self.childerr = os.fdopen(errout, 'r', bufsize)
55  else:
56  self.childerr = None
57  _active.append(self)
58 
59  def _run_child(self, cmd):
60  if isinstance(cmd, types.StringTypes):
61  cmd = ['/bin/sh', '-c', cmd]
62  for i in range(3, MAXFD):
63  try:
64  os.close(i)
65  except:
66  pass
67  try:
68  os.execvp(cmd[0], cmd)
69  finally:
70  os._exit(1)
71 
72  def poll(self):
73  """Return the exit status of the child process if it has finished,
74  or -1 if it hasn't finished yet."""
75  if self.sts < 0:
76  try:
77  pid, sts = os.waitpid(self.pid, os.WNOHANG)
78  if pid == self.pid:
79  self.sts = sts
80  _active.remove(self)
81  except os.error:
82  pass
83  return self.sts
84 
85  def wait(self):
86  """Wait for and return the exit status of the child process."""
87  pid, sts = os.waitpid(self.pid, 0)
88  if pid == self.pid:
89  self.sts = sts
90  _active.remove(self)
91  return self.sts
92 
93 
94 class Popen4(Popen3):
95  childerr = None
96 
97  def __init__(self, cmd, bufsize=-1):
98  _cleanup()
99  p2cread, p2cwrite = os.pipe()
100  c2pread, c2pwrite = os.pipe()
101  self.pid = os.fork()
102  if self.pid == 0:
103  # Child
104  os.dup2(p2cread, 0)
105  os.dup2(c2pwrite, 1)
106  os.dup2(c2pwrite, 2)
107  self._run_child(cmd)
108  os.close(p2cread)
109  self.tochild = os.fdopen(p2cwrite, 'w', bufsize)
110  os.close(c2pwrite)
111  self.fromchild = os.fdopen(c2pread, 'r', bufsize)
112  _active.append(self)
113 
114 
115 if sys.platform[:3] == "win":
116  # Some things don't make sense on non-Unix platforms.
117  del Popen3, Popen4
118 
119  def popen2(cmd, bufsize=-1, mode='t'):
120  """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is
121  specified, it sets the buffer size for the I/O pipes. The file objects
122  (child_stdout, child_stdin) are returned."""
123  w, r = os.popen2(cmd, mode, bufsize)
124  return r, w
125 
126  def popen3(cmd, bufsize=-1, mode='t'):
127  """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is
128  specified, it sets the buffer size for the I/O pipes. The file objects
129  (child_stdout, child_stdin, child_stderr) are returned."""
130  w, r, e = os.popen3(cmd, mode, bufsize)
131  return r, w, e
132 
133  def popen4(cmd, bufsize=-1, mode='t'):
134  """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is
135  specified, it sets the buffer size for the I/O pipes. The file objects
136  (child_stdout_stderr, child_stdin) are returned."""
137  w, r = os.popen4(cmd, mode, bufsize)
138  return r, w
139 else:
140  def popen2(cmd, bufsize=-1, mode='t'):
141  """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is
142  specified, it sets the buffer size for the I/O pipes. The file objects
143  (child_stdout, child_stdin) are returned."""
144  inst = Popen3(cmd, 0, bufsize)
145  return inst.fromchild, inst.tochild
146 
147  def popen3(cmd, bufsize=-1, mode='t'):
148  """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is
149  specified, it sets the buffer size for the I/O pipes. The file objects
150  (child_stdout, child_stdin, child_stderr) are returned."""
151  inst = Popen3(cmd, 1, bufsize)
152  return inst.fromchild, inst.tochild, inst.childerr
153 
154  def popen4(cmd, bufsize=-1, mode='t'):
155  """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is
156  specified, it sets the buffer size for the I/O pipes. The file objects
157  (child_stdout_stderr, child_stdin) are returned."""
158  inst = Popen4(cmd, bufsize)
159  return inst.fromchild, inst.tochild
160 
161  __all__.extend(["Popen3", "Popen4"])
162 
163 def _test():
164  cmd = "cat"
165  teststr = "ab cd\n"
166  if os.name == "nt":
167  cmd = "more"
168  # "more" doesn't act the same way across Windows flavors,
169  # sometimes adding an extra newline at the start or the
170  # end. So we strip whitespace off both ends for comparison.
171  expected = teststr.strip()
172  print "testing popen2..."
173  r, w = popen2(cmd)
174  w.write(teststr)
175  w.close()
176  got = r.read()
177  if got.strip() != expected:
178  raise ValueError("wrote %s read %s" % (`teststr`, `got`))
179  print "testing popen3..."
180  try:
181  r, w, e = popen3([cmd])
182  except:
183  r, w, e = popen3(cmd)
184  w.write(teststr)
185  w.close()
186  got = r.read()
187  if got.strip() != expected:
188  raise ValueError("wrote %s read %s" % (`teststr`, `got`))
189  got = e.read()
190  if got:
191  raise ValueError("unexected %s on stderr" % `got`)
192  for inst in _active[:]:
193  inst.wait()
194  if _active:
195  raise ValueError("_active not empty")
196  print "All OK"
197 
198 if __name__ == '__main__':
199  _test()