~malept/ubuntu/lucid/python2.6/dev-dependency-fix

« back to all changes in this revision

Viewing changes to Lib/popen2.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-02-13 12:51:00 UTC
  • Revision ID: james.westby@ubuntu.com-20090213125100-uufgcb9yeqzujpqw
Tags: upstream-2.6.1
ImportĀ upstreamĀ versionĀ 2.6.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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"])