X-Git-Url: https://code.delx.au/transcoding/blobdiff_plain/84b0228355acac61d0c5d0ce35d111d0f9e25cd3..d395206f2969ec7835372e1553f90bcb1b882098:/batchrun.py diff --git a/batchrun.py b/batchrun.py index 49fae69..fa799df 100755 --- a/batchrun.py +++ b/batchrun.py @@ -1,17 +1,28 @@ #!/usr/bin/env python -import optparse, shlex, subprocess, sys, itertools +import itertools +import optparse +import os +import shlex +import subprocess +import sys +import time -def parseArgs(): - parser = optparse.OptionParser(usage="%prog batchfile1 [batchfile2] ...") - opts, args = parser.parse_args(sys.argv[1:]) - return args -def run(args): - subprocess.Popen(args).wait() +def run(running_jobs, cmd): + p = subprocess.Popen(cmd, stdin=file(os.devnull, 'r')) + running_jobs.append(p) + +def wait_for_completion(max_jobs, running_jobs): + while len(running_jobs) >= max_jobs: + time.sleep(1) + for job in running_jobs: + if job.poll() is not None: + running_jobs.remove(job) + job.wait() -def getblocks(fd): - def _countIndentationLevel(s): +def parse_file(fd): + def count_indent(s): level = 0 for ch in s: if ch == "\t": @@ -21,31 +32,47 @@ def getblocks(fd): return level for line in fd: - level = _countIndentationLevel(line) + if not line.strip(): + continue # Ignore blank lines + level = count_indent(line) line = line[level:] # Slice off the indentation yield level, line - -def batchProcess(fd): - opts = [] + yield 0, None - for level, line in getblocks(fd): - oldLevel = len(opts) - 1 - if level <= oldLevel: - run(itertools.chain(*opts)) +def batch_process(opts, lines): + running_jobs = [] + cmd = [] - opts = opts[:level] # Delete all options that belong to groups that are indented more than this one - assert len(opts) == level, 'Seems we missed some options somewhere' + for level, line in lines: + old_level = len(cmd) - 1 + if level <= old_level: + run(running_jobs, itertools.chain(*cmd)) + wait_for_completion(opts.jobs, running_jobs) - opts.append(shlex.split(line)) + # Delete all options that belong to groups that are indented more than + # this one + cmd = cmd[:level] + assert len(cmd) == level - if len(opts) > 0: - run(itertools.chain(*opts)) + if line: + cmd.append(shlex.split(line)) + # Wait for remaining jobs to finish + wait_for_completion(1, running_jobs) + +def parse_args(): + parser = optparse.OptionParser(usage="%prog batchfile1 [batchfile2] ...") + parser.add_option("-j", "--jobs", + action="store", dest="jobs", default=1, type="int", + help="The number of concurrent jobs to run") + opts, args = parser.parse_args(sys.argv[1:]) + opts.running_jobs = [] + return opts, args def main(): - args = parseArgs() + opts, args = parse_args() for name in args: - batchProcess(open(name)) + batch_process(opts, parse_file(open(name))) if __name__ == "__main__": main()