PyXR

c:\python24\lib \ popen2.py



0001 """Spawn a command with pipes to its stdin, stdout, and optionally stderr.
0002 
0003 The normal os.popen(cmd, mode) call spawns a shell command and provides a
0004 file interface to just the input or output of the process depending on
0005 whether mode is 'r' or 'w'.  This module provides the functions popen2(cmd)
0006 and popen3(cmd) which return two or three pipes to the spawned command.
0007 """
0008 
0009 import os
0010 import sys
0011 
0012 __all__ = ["popen2", "popen3", "popen4"]
0013 
0014 try:
0015     MAXFD = os.sysconf('SC_OPEN_MAX')
0016 except (AttributeError, ValueError):
0017     MAXFD = 256
0018 
0019 _active = []
0020 
0021 def _cleanup():
0022     for inst in _active[:]:
0023         inst.poll()
0024 
0025 class Popen3:
0026     """Class representing a child process.  Normally instances are created
0027     by the factory functions popen2() and popen3()."""
0028 
0029     sts = -1                    # Child not completed yet
0030 
0031     def __init__(self, cmd, capturestderr=False, bufsize=-1):
0032         """The parameter 'cmd' is the shell command to execute in a
0033         sub-process.  On UNIX, 'cmd' may be a sequence, in which case arguments
0034         will be passed directly to the program without shell intervention (as
0035         with os.spawnv()).  If 'cmd' is a string it will be passed to the shell
0036         (as with os.system()).   The 'capturestderr' flag, if true, specifies
0037         that the object should capture standard error output of the child
0038         process.  The default is false.  If the 'bufsize' parameter is
0039         specified, it specifies the size of the I/O buffers to/from the child
0040         process."""
0041         _cleanup()
0042         p2cread, p2cwrite = os.pipe()
0043         c2pread, c2pwrite = os.pipe()
0044         if capturestderr:
0045             errout, errin = os.pipe()
0046         self.pid = os.fork()
0047         if self.pid == 0:
0048             # Child
0049             os.dup2(p2cread, 0)
0050             os.dup2(c2pwrite, 1)
0051             if capturestderr:
0052                 os.dup2(errin, 2)
0053             self._run_child(cmd)
0054         os.close(p2cread)
0055         self.tochild = os.fdopen(p2cwrite, 'w', bufsize)
0056         os.close(c2pwrite)
0057         self.fromchild = os.fdopen(c2pread, 'r', bufsize)
0058         if capturestderr:
0059             os.close(errin)
0060             self.childerr = os.fdopen(errout, 'r', bufsize)
0061         else:
0062             self.childerr = None
0063         _active.append(self)
0064 
0065     def _run_child(self, cmd):
0066         if isinstance(cmd, basestring):
0067             cmd = ['/bin/sh', '-c', cmd]
0068         for i in range(3, MAXFD):
0069             try:
0070                 os.close(i)
0071             except OSError:
0072                 pass
0073         try:
0074             os.execvp(cmd[0], cmd)
0075         finally:
0076             os._exit(1)
0077 
0078     def poll(self):
0079         """Return the exit status of the child process if it has finished,
0080         or -1 if it hasn't finished yet."""
0081         if self.sts < 0:
0082             try:
0083                 pid, sts = os.waitpid(self.pid, os.WNOHANG)
0084                 if pid == self.pid:
0085                     self.sts = sts
0086                     _active.remove(self)
0087             except os.error:
0088                 pass
0089         return self.sts
0090 
0091     def wait(self):
0092         """Wait for and return the exit status of the child process."""
0093         if self.sts < 0:
0094             pid, sts = os.waitpid(self.pid, 0)
0095             if pid == self.pid:
0096                 self.sts = sts
0097                 _active.remove(self)
0098         return self.sts
0099 
0100 
0101 class Popen4(Popen3):
0102     childerr = None
0103 
0104     def __init__(self, cmd, bufsize=-1):
0105         _cleanup()
0106         p2cread, p2cwrite = os.pipe()
0107         c2pread, c2pwrite = os.pipe()
0108         self.pid = os.fork()
0109         if self.pid == 0:
0110             # Child
0111             os.dup2(p2cread, 0)
0112             os.dup2(c2pwrite, 1)
0113             os.dup2(c2pwrite, 2)
0114             self._run_child(cmd)
0115         os.close(p2cread)
0116         self.tochild = os.fdopen(p2cwrite, 'w', bufsize)
0117         os.close(c2pwrite)
0118         self.fromchild = os.fdopen(c2pread, 'r', bufsize)
0119         _active.append(self)
0120 
0121 
0122 if sys.platform[:3] == "win" or sys.platform == "os2emx":
0123     # Some things don't make sense on non-Unix platforms.
0124     del Popen3, Popen4
0125 
0126     def popen2(cmd, bufsize=-1, mode='t'):
0127         """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
0128         be a sequence, in which case arguments will be passed directly to the
0129         program without shell intervention (as with os.spawnv()). If 'cmd' is a
0130         string it will be passed to the shell (as with os.system()). If
0131         'bufsize' is specified, it sets the buffer size for the I/O pipes. The
0132         file objects (child_stdout, child_stdin) are returned."""
0133         w, r = os.popen2(cmd, mode, bufsize)
0134         return r, w
0135 
0136     def popen3(cmd, bufsize=-1, mode='t'):
0137         """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
0138         be a sequence, in which case arguments will be passed directly to the
0139         program without shell intervention (as with os.spawnv()). If 'cmd' is a
0140         string it will be passed to the shell (as with os.system()). If
0141         'bufsize' is specified, it sets the buffer size for the I/O pipes. The
0142         file objects (child_stdout, child_stdin, child_stderr) are returned."""
0143         w, r, e = os.popen3(cmd, mode, bufsize)
0144         return r, w, e
0145 
0146     def popen4(cmd, bufsize=-1, mode='t'):
0147         """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
0148         be a sequence, in which case arguments will be passed directly to the
0149         program without shell intervention (as with os.spawnv()). If 'cmd' is a
0150         string it will be passed to the shell (as with os.system()). If
0151         'bufsize' is specified, it sets the buffer size for the I/O pipes. The
0152         file objects (child_stdout_stderr, child_stdin) are returned."""
0153         w, r = os.popen4(cmd, mode, bufsize)
0154         return r, w
0155 else:
0156     def popen2(cmd, bufsize=-1, mode='t'):
0157         """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
0158         be a sequence, in which case arguments will be passed directly to the
0159         program without shell intervention (as with os.spawnv()). If 'cmd' is a
0160         string it will be passed to the shell (as with os.system()). If
0161         'bufsize' is specified, it sets the buffer size for the I/O pipes. The
0162         file objects (child_stdout, child_stdin) are returned."""
0163         inst = Popen3(cmd, False, bufsize)
0164         return inst.fromchild, inst.tochild
0165 
0166     def popen3(cmd, bufsize=-1, mode='t'):
0167         """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
0168         be a sequence, in which case arguments will be passed directly to the
0169         program without shell intervention (as with os.spawnv()). If 'cmd' is a
0170         string it will be passed to the shell (as with os.system()). If
0171         'bufsize' is specified, it sets the buffer size for the I/O pipes. The
0172         file objects (child_stdout, child_stdin, child_stderr) are returned."""
0173         inst = Popen3(cmd, True, bufsize)
0174         return inst.fromchild, inst.tochild, inst.childerr
0175 
0176     def popen4(cmd, bufsize=-1, mode='t'):
0177         """Execute the shell command 'cmd' in a sub-process. On UNIX, 'cmd' may
0178         be a sequence, in which case arguments will be passed directly to the
0179         program without shell intervention (as with os.spawnv()). If 'cmd' is a
0180         string it will be passed to the shell (as with os.system()). If
0181         'bufsize' is specified, it sets the buffer size for the I/O pipes. The
0182         file objects (child_stdout_stderr, child_stdin) are returned."""
0183         inst = Popen4(cmd, bufsize)
0184         return inst.fromchild, inst.tochild
0185 
0186     __all__.extend(["Popen3", "Popen4"])
0187 
0188 def _test():
0189     cmd  = "cat"
0190     teststr = "ab cd\n"
0191     if os.name == "nt":
0192         cmd = "more"
0193     # "more" doesn't act the same way across Windows flavors,
0194     # sometimes adding an extra newline at the start or the
0195     # end.  So we strip whitespace off both ends for comparison.
0196     expected = teststr.strip()
0197     print "testing popen2..."
0198     r, w = popen2(cmd)
0199     w.write(teststr)
0200     w.close()
0201     got = r.read()
0202     if got.strip() != expected:
0203         raise ValueError("wrote %r read %r" % (teststr, got))
0204     print "testing popen3..."
0205     try:
0206         r, w, e = popen3([cmd])
0207     except:
0208         r, w, e = popen3(cmd)
0209     w.write(teststr)
0210     w.close()
0211     got = r.read()
0212     if got.strip() != expected:
0213         raise ValueError("wrote %r read %r" % (teststr, got))
0214     got = e.read()
0215     if got:
0216         raise ValueError("unexected %r on stderr" % (got,))
0217     for inst in _active[:]:
0218         inst.wait()
0219     if _active:
0220         raise ValueError("_active not empty")
0221     print "All OK"
0222 
0223 if __name__ == '__main__':
0224     _test()
0225 

Generated by PyXR 0.9.4
SourceForge.net Logo