Mercurial > hg > config
comparison python/multiproc.py @ 611:8e23bbc9c197
STUB: python/multiproc.py
| author | Jeff Hammel <k0scist@gmail.com> |
|---|---|
| date | Sun, 02 Feb 2014 15:32:29 -0800 |
| parents | 5ce25399da67 |
| children | 839dfd35d567 |
comparison
equal
deleted
inserted
replaced
| 610:5ce25399da67 | 611:8e23bbc9c197 |
|---|---|
| 16 class Process(subprocess.Popen): | 16 class Process(subprocess.Popen): |
| 17 """why would you name a subprocess object Popen?""" | 17 """why would you name a subprocess object Popen?""" |
| 18 | 18 |
| 19 # http://docs.python.org/2/library/subprocess.html#popen-constructor | 19 # http://docs.python.org/2/library/subprocess.html#popen-constructor |
| 20 defaults = {'bufsize': 1, # line buffered | 20 defaults = {'bufsize': 1, # line buffered |
| 21 'store_output': True, # store stdout | |
| 21 } | 22 } |
| 22 | 23 |
| 23 def __init__(self, command, **kwargs): | 24 def __init__(self, command, **kwargs): |
| 24 | 25 |
| 25 # setup arguments | 26 # setup arguments |
| 31 # type of command (string or list) | 32 # type of command (string or list) |
| 32 if not subprocess.mswindows: | 33 if not subprocess.mswindows: |
| 33 _kwargs['shell'] = isinstance(command, string) | 34 _kwargs['shell'] = isinstance(command, string) |
| 34 | 35 |
| 35 # output buffer | 36 # output buffer |
| 37 self.location = 0 | |
| 36 self.output_buffer = tempfile.SpooledTemporaryFile() | 38 self.output_buffer = tempfile.SpooledTemporaryFile() |
| 37 self.location = 0 | 39 self.output = '' if _kwargs.pop('store_output') else None |
| 38 self.output = '' | |
| 39 _kwargs['stdout'] = self.output_buffer | 40 _kwargs['stdout'] = self.output_buffer |
| 40 | 41 |
| 42 # runtime | |
| 43 self.start = time.time() | |
| 44 self.end = None | |
| 45 | |
| 41 # launch subprocess | 46 # launch subprocess |
| 42 self.start = time.time() | |
| 43 subprocess.Popen.__init__(self, command, **_kwargs) | 47 subprocess.Popen.__init__(self, command, **_kwargs) |
| 44 | 48 |
| 45 def wait(self, maxtime=None, sleep=1.): | 49 def _finalize(self, process_output): |
| 50 """internal function to finalize""" | |
| 51 | |
| 52 # read final output | |
| 53 self.read(process_output) | |
| 54 | |
| 55 # reset output buffer | |
| 56 self.output_buffer.seek(0) | |
| 57 | |
| 58 # set end time | |
| 59 self.end = time.time() | |
| 60 | |
| 61 def wait(self, maxtime=None, sleep=1., process_output=None): | |
| 46 """ | 62 """ |
| 47 maxtime -- timeout in seconds | 63 maxtime -- timeout in seconds |
| 48 sleep -- number of seconds to sleep between polling | 64 sleep -- number of seconds to sleep between polling |
| 49 """ | 65 """ |
| 50 while self.poll() is None: | 66 while self.poll() is None: |
| 51 | 67 |
| 52 # check for timeout | 68 # check for timeout |
| 53 curr_time = time.time() | 69 curr_time = time.time() |
| 54 run_time = curr_time - self.start | 70 run_time = curr_time - self.start |
| 55 if run_time > maxtime: | 71 if run_time > maxtime: |
| 56 # TODO: read from output | 72 self.kill() |
| 57 return process.kill() | 73 self._finalize(process_output) |
| 74 return | |
| 58 | 75 |
| 59 # read from output buffer | 76 # read from output buffer |
| 60 read = self.read() | 77 self.read(process_output) |
| 61 | 78 |
| 62 # naptime | 79 # naptime |
| 63 if sleep: | 80 if sleep: |
| 64 time.sleep(sleep) | 81 time.sleep(sleep) |
| 65 | 82 |
| 66 # reset tempfile | 83 # finalize |
| 67 output.seek(0) | 84 self._finalize() |
| 68 | 85 |
| 69 return self.returncode # set by ``.poll()`` | 86 return self.returncode # set by ``.poll()`` |
| 70 | 87 |
| 71 def read(self): | 88 def read(self, process_output=None): |
| 72 """read from the output buffer""" | 89 """read from the output buffer""" |
| 90 | |
| 73 self.output_buffer.seek(self.location) | 91 self.output_buffer.seek(self.location) |
| 74 read = self.output_buffer.read() | 92 read = self.output_buffer.read() |
| 75 self.output += read | 93 if self.output is not None: |
| 94 self.output += read | |
| 95 if process_output: | |
| 96 process_output(read) | |
| 76 self.location += len(read) | 97 self.location += len(read) |
| 77 return read | 98 return read |
| 78 | 99 |
| 79 def commandline(self): | 100 def commandline(self): |
| 80 """returns string of command line""" | 101 """returns string of command line""" |
| 83 return self.command | 104 return self.command |
| 84 return subprocess.list2cmdline(self.command) | 105 return subprocess.list2cmdline(self.command) |
| 85 | 106 |
| 86 __str__ = commandline | 107 __str__ = commandline |
| 87 | 108 |
| 109 def runtime(self): | |
| 110 """returns time spent running or total runtime if completed""" | |
| 111 | |
| 112 if self.end is None: | |
| 113 return self.end - self.start | |
| 114 return time.time() - self.start | |
| 115 | |
| 88 | 116 |
| 89 def main(args=sys.argv[1:]): | 117 def main(args=sys.argv[1:]): |
| 90 """CLI""" | 118 """CLI""" |
| 91 | 119 |
| 92 # available programs | 120 # available programs |
| 93 progs = {'yes': ["yes"], | 121 progs = {'yes': ["yes"], |
| 94 'ping': ['ping', 'google.com']} | 122 'ping': ['ping', 'google.com']} |
| 95 | 123 |
| 96 | |
| 97 # parse command line | 124 # parse command line |
| 98 usage = '%prog [options]' | 125 parser = argparse.ArgumentParser(description=__doc__) |
| 99 parser = argparse.ArgumentParser(usage=usage, description=__doc__) | |
| 100 parser.add_argument("-t", "--time", dest="time", | 126 parser.add_argument("-t", "--time", dest="time", |
| 101 type=float, default=4., | 127 type=float, default=4., |
| 102 help="seconds to run for") | 128 help="seconds to run for") |
| 103 parser.add_argument("-s", "--sleep", dest="sleep", | 129 parser.add_argument("-s", "--sleep", dest="sleep", |
| 104 type=float, default=1., | 130 type=float, default=1., |
| 118 sys.exit(0) | 144 sys.exit(0) |
| 119 | 145 |
| 120 # select program | 146 # select program |
| 121 prog = progs[options.program] | 147 prog = progs[options.program] |
| 122 | 148 |
| 149 # start process | |
| 123 proc = Process(prog) | 150 proc = Process(prog) |
| 151 | |
| 152 # callback for output processing | |
| 153 def process_output(output): | |
| 154 print output.upper() | |
| 124 | 155 |
| 125 # # start the main subprocess loop | 156 # # start the main subprocess loop |
| 126 # # TODO -> OO | 157 # # TODO -> OO |
| 127 # output = tempfile.SpooledTemporaryFile() | 158 # output = tempfile.SpooledTemporaryFile() |
| 128 # start = time.time() | 159 # start = time.time() |
| 141 # time.sleep(options.sleep) | 172 # time.sleep(options.sleep) |
| 142 | 173 |
| 143 # # reset tempfile | 174 # # reset tempfile |
| 144 # output.seek(0) | 175 # output.seek(0) |
| 145 | 176 |
| 146 n_lines = len(output.read().splitlines()) | 177 # wait for being done |
| 178 proc.wait(maxtime=options.time, sleep=options.sleep, process_output=process_output) | |
| 179 | |
| 180 # finalization | |
| 181 output = proc.output | |
| 182 n_lines = len(output.splitlines()) | |
| 147 print ("{}: {} lines".format(subprocess.list2cmdline(prog), n_lines)) | 183 print ("{}: {} lines".format(subprocess.list2cmdline(prog), n_lines)) |
| 148 | 184 |
| 149 if __name__ == '__main__': | 185 if __name__ == '__main__': |
| 150 main() | 186 main() |
