2 warnings.warn("eventlet.processes is deprecated in favor of "
3 "eventlet.green.subprocess, which is API-compatible with the standard "
4 " library subprocess module.",
5 DeprecationWarning, stacklevel=2)
12 from eventlet import greenio, pools
13 from eventlet.green import subprocess
16 class DeadProcess(RuntimeError):
20 def cooperative_wait(pobj, check_interval=0.01):
21 """ Waits for a child process to exit, returning the status
24 Unlike ``os.wait``, :func:`cooperative_wait` does not block the entire
25 process, only the calling coroutine. If the child process does not die,
26 :func:`cooperative_wait` could wait forever.
28 The argument *check_interval* is the amount of time, in seconds, that
29 :func:`cooperative_wait` will sleep between calls to ``os.waitpid``.
36 eventlet.sleep(check_interval)
38 if e.errno == errno.ECHILD:
39 # no child process, this happens if the child process
40 # already died and has been cleaned up, or if you just
41 # called with a random pid value
47 class Process(object):
48 """Construct Process objects, then call read, and write on them."""
51 def __init__(self, command, args, dead_callback=None):
52 self.process_number = self.process_number + 1
53 Process.process_number = self.process_number
54 self.command = command
56 self._dead_callback = dead_callback
65 args.extend(self.args)
66 self.proc = subprocess.Popen(
69 stdin=subprocess.PIPE,
70 stdout=subprocess.PIPE,
71 stderr=subprocess.STDOUT,
74 self.child_stdout_stderr = self.proc.stdout
75 self.child_stdin = self.proc.stdin
77 self.sendall = self.child_stdin.write
78 self.send = self.child_stdin.write
79 self.recv = self.child_stdout_stderr.read
80 self.readline = self.child_stdout_stderr.readline
81 self._read_first_result = False
84 return cooperative_wait(self.proc)
86 def dead_callback(self):
89 if self._dead_callback:
92 def makefile(self, mode, *arg):
93 if mode.startswith('r'):
94 return self.child_stdout_stderr
95 if mode.startswith('w'):
96 return self.child_stdin
97 raise RuntimeError("Unknown mode", mode)
99 def read(self, amount=None):
100 """Reads from the stdout and stderr of the child process.
101 The first call to read() will return a string; subsequent
102 calls may raise a DeadProcess when EOF occurs on the pipe.
104 result = self.child_stdout_stderr.read(amount)
105 if result == '' and self._read_first_result:
106 # This process is dead.
110 self._read_first_result = True
113 def write(self, stuff):
116 written = self.child_stdin.write(stuff)
117 self.child_stdin.flush()
118 except ValueError as e:
120 assert str(e) == 'I/O operation on closed file'
126 self.child_stdin.flush()
129 self.child_stdout_stderr.close()
130 self.child_stdin.close()
133 def close_stdin(self):
134 self.child_stdin.close()
136 def kill(self, sig=None):
146 class ProcessPool(pools.Pool):
147 def __init__(self, command, args=None, min_size=0, max_size=4):
151 self.command = command
155 pools.Pool.__init__(self, min_size, max_size)
158 """Generate a process
161 self.current_size -= 1
162 return Process(self.command, self.args, dead_callback)
166 if item.proc.poll() != -1:
169 pools.Pool.put(self, item)