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()