changeset 584:9f5691d5587d

added command line options
author Olivier Breuleux <breuleuo@iro.umontreal.ca>
date Fri, 05 Dec 2008 17:05:06 -0500
parents a83f62555c57
children 4e25f4e90c1e
files pylearn/dbdict/newstuff.py
diffstat 1 files changed, 83 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/pylearn/dbdict/newstuff.py	Thu Dec 04 17:07:29 2008 -0500
+++ b/pylearn/dbdict/newstuff.py	Fri Dec 05 17:05:06 2008 -0500
@@ -447,10 +447,23 @@
 ### running
 ################################################################################
 
-def run(type, arguments):
-    runner = runner_registry.get(type, None)
+import optparse
+OptionParser = optparse.OptionParser
+# class OptionParser(optparse.OptionParser):
+#     def error(self, message):
+#         pass
+
+def parse_and_run(command, arguments):
+    parser, runner = runner_registry.get(command, (None, None))
     if not runner:
-        raise UsageError('Unknown runner: "%s"' % type)
+        raise UsageError('Unknown runner: "%s"' % command)
+    if parser:
+        options, arguments = parser.parse_args(arguments)
+    else:
+        options = optparse.Values()
+    run(runner, [options] + arguments)
+
+def run(runner, arguments):
     argspec = inspect.getargspec(runner)
     minargs = len(argspec[0])-(len(argspec[3]) if argspec[3] else 0)
     maxargs = len(argspec[0])
@@ -461,11 +474,24 @@
 
 runner_registry = dict()
 
-def runner_cmdline(experiment, *strings):
+
+parser_cmdline = OptionParser(usage = '%prog cmdline [options] <experiment> <parameters>')
+parser_cmdline.add_option('-f', '--force', action = 'store_true', dest = 'force', default = False,
+                          help = 'force running the experiment even if it is already running or completed')
+parser_cmdline.add_option('--redirect-stdout', action = 'store_true', dest = 'redirect_stdout', default = False,
+                          help = 'redirect stdout to the workdir/stdout file')
+parser_cmdline.add_option('--redirect-stderr', action = 'store_true', dest = 'redirect_stderr', default = False,
+                          help = 'redirect stderr to the workdir/stdout file')
+parser_cmdline.add_option('-r', '--redirect', action = 'store_true', dest = 'redirect', default = False,
+                          help = 'redirect stdout and stderr to the workdir/stdout and workdir/stderr files')
+parser_cmdline.add_option('-w', '--workdir', action = 'store', dest = 'workdir', default = None,
+                          help = 'the working directory in which to run the experiment')
+
+def runner_cmdline(options, experiment, *strings):
     """
     Start an experiment with parameters given on the command line.
 
-    Usage: cmdline <experiment> <parameters>
+    Usage: cmdline [options] <experiment> <parameters>
 
     Run an experiment with parameters provided on the command
     line. See the help topics for experiment and parameters for
@@ -480,15 +506,20 @@
     state = expand(parse(*strings))
     state.dbdict.experiment = experiment
     experiment = resolve(experiment)
-    #channel = RSyncChannel('.', 'yaddayadda', experiment, state)
-    channel = StandardChannel(format_d(state, sep=',', space = False),
-                              experiment, state)
-    channel.run()
+    workdir = options.workdir or format_d(state, sep=',', space = False)
+    channel = StandardChannel(workdir,
+                              experiment, state,
+                              redirect_stdout = options.redirect or options.redirect_stdout,
+                              redirect_stderr = options.redirect or options.redirect_stderr)
+    channel.run(force = options.force)
 
-runner_registry['cmdline'] = runner_cmdline
+runner_registry['cmdline'] = (parser_cmdline, runner_cmdline)
 
 
-def runner_sqlschedule(dbdescr, experiment, *strings):
+
+parser_sqlschedule = OptionParser(usage = '%prog sqlschedule [options] <tablepath> <experiment> <parameters>')
+
+def runner_sqlschedule(options, dbdescr, experiment, *strings):
     """
     Schedule a job to run using the sql command.
 
@@ -540,11 +571,16 @@
     state['dbdict.experiment'] = experiment
     sql.add_experiments_to_db([state], db, verbose = 1)
 
-runner_registry['sqlschedule'] = runner_sqlschedule
+runner_registry['sqlschedule'] = (parser_sqlschedule, runner_sqlschedule)
 
 
 
-def runner_sql(dbdescr, exproot):
+parser_sql = OptionParser(usage = '%prog sql [options] <tablepath> <exproot>')
+parser_sql.add_option('-n', dest = 'n', type = 'int', default = 1,
+                      help = 'Run N experiments sequentially (default 1) '
+                      '(if N is <= 0, runs as many experiments as possible).')
+
+def runner_sql(options, dbdescr, exproot):
     """
     Run jobs from a sql table.
 
@@ -559,9 +595,9 @@
         postgres://user:pass@host/dbname/tablename
 
     exproot can be a local path or a remote path. Examples of exproots:
-      /some/local/path
-      ssh://some_host:/some/remote/path # relative to the filesystem root
-      ssh://some_host:other/remote/path # relative to the HOME on some_host
+        /some/local/path
+        ssh://some_host:/some/remote/path # relative to the filesystem root
+        ssh://some_host:other/remote/path # relative to the HOME on some_host
 
     The exproot will contain a subdirectory hierarchy corresponding to
     the dbname, tablename and job id which is a unique integer.
@@ -582,23 +618,33 @@
             = sql.parse_dbstring(dbdescr)
     except:
         raise UsageError('Wrong syntax for dbdescr')
-    workdir = tempfile.mkdtemp()
-    #print 'wdir', workdir
-    channel = DBRSyncChannel(username, password, hostname, dbname, tablename,
-                             workdir,
-                             exproot,
-                             redirect_stdout = True,
-                             redirect_stderr = True)
-    channel.run()
-    shutil.rmtree(workdir, ignore_errors=True)
 
-runner_registry['sql'] = runner_sql
+    n = options.n if options.n else -1
+    nrun = 0
+    try:
+        while n != 0:
+            workdir = tempfile.mkdtemp()
+            #print 'wdir', workdir
+            channel = DBRSyncChannel(username, password, hostname, dbname, tablename,
+                                     workdir,
+                                     exproot,
+                                     redirect_stdout = True,
+                                     redirect_stderr = True)
+            channel.run()
+            shutil.rmtree(workdir, ignore_errors=True)
+            n -= 1
+            nrun += 1
+    except JobError, e:
+        if e.args[0] == JobError.NOJOB:
+            print 'No more jobs to run (run %i jobs)' % nrun
+
+runner_registry['sql'] = (parser_sql, runner_sql)
 
     
 
 
 
-def help(topic = None):
+def runner_help(options, topic = None):
     """
     Get help for a topic.
 
@@ -757,7 +803,7 @@
                            some_param=1 \\
                            other_param=0.4
 
-        dbdict-run sql postgres://user:pass@host/dbname/tablename workdir
+        dbdict-run sql postgres://user:pass@host/dbname/tablename exproot
 
         You need to make sure that the module `my_experiments` is accessible
         from python. You can check with the command
@@ -768,7 +814,7 @@
         helptext = runner_registry.get(topic, None)
     print format_help(helptext)
 
-runner_registry['help'] = help
+runner_registry['help'] = (None, runner_help)
 
 ################################################################################
 ### main
@@ -778,7 +824,14 @@
     try:
         if len(sys.argv) <= 1:
             raise UsageError('Usage: %s <run_type> [<arguments>*]' % sys.argv[0])
-        run(sys.argv[1], sys.argv[2:])
+        cmd = None
+        args = []
+        for arg in sys.argv[1:]:
+            if cmd is not None or arg.startswith('-'):
+                args.append(arg)
+            else:
+                cmd = arg
+        parse_and_run(cmd, args)
     except UsageError, e:
         print 'Usage error:'
         print e