3
from __future__ import print_function
5
from argparse import ArgumentParser
6
from contextlib import contextmanager
13
from utility import configure_logging
19
log = logging.getLogger("concurrently")
24
def __init__(self, name_commdline, log_dir='.'):
25
self.name, self.commandline = name_commdline.split('=', 1)
26
self.command = self.commandline.split()
27
self.out_log_name = os.path.join(
28
log_dir, '{}-out.log'.format(self.name))
29
self.err_log_name = os.path.join(
30
log_dir, '{}-err.log'.format(self.name))
31
self.returncode = None
34
def __eq__(self, other):
35
if type(self) != type(other):
37
return (self.name == other.name and
38
self.command == other.command and
39
self.out_log_name == other.out_log_name and
40
self.err_log_name == other.err_log_name)
44
"""Yield the running proc, then wait to set the returncode."""
45
with open(self.out_log_name, 'ab') as out_log:
46
with open(self.err_log_name, 'ab') as err_log:
47
self.proc = subprocess.Popen(
48
self.command, stdout=out_log, stderr=err_log)
49
log.debug('Started {}'.format(self.name))
53
log.debug('Waiting for {} to finish'.format(self.name))
54
self.returncode = self.proc.wait()
55
log.debug('{} finished'.format(self.name))
59
"""Run all tasks in the list.
61
The list is a queue that will be emptied.
72
def summarise_tasks(tasks):
73
"""Return of sum of tasks returncodes."""
74
returncode = sum([t.returncode for t in tasks])
80
if task.returncode != 0:
81
log.error('{} failed with {}\nSee {}'.format(
82
task.name, task.returncode, task.err_log_name))
86
def parse_args(argv=None):
87
"""Return the parsed args for this program."""
88
parser = ArgumentParser(
89
description="Run many tasks concurrently.")
91
'-v', '--verbose', action='store_const',
92
default=logging.INFO, const=logging.DEBUG,
93
help='Increase verbosity.')
95
'-l', '--log_dir', default='.', type=os.path.expanduser,
96
help='The path to store the logs for each task.')
98
'tasks', nargs='+', default=[],
99
help="one or more tasks to run in the form of name='cmc -opt arg'.")
100
return parser.parse_args(argv)
104
"""Run many tasks concurrently."""
106
args = parse_args(argv)
107
configure_logging(args.verbose)
108
tasks = [Task(t, args.log_dir) for t in args.tasks]
110
names = [t.name for t in tasks]
111
log.debug('Running these tasks {}'.format(names))
113
returncode = summarise_tasks(tasks)
114
except Exception as e:
116
log.error(traceback.print_exc())
121
if __name__ == '__main__':