def main():
    """
    The main function of the Andes command-line tool.

    This function executes the following workflow:

     * Parse the command line inputs
     * Show the tool preamble
     * Output the requested helps, edit/save configs or remove outputs. Exit
       the main program if any of the above is executed
     * Process the input files and call ``main.run()`` using single- or
       multi-processing
     * Show the execution time and exit

    Returns
    -------
    None
    """
    t0, s = elapsed()

    # parser command line arguments
    args = vars(cli_new())

    # configure stream handler verbose level
    config_logger(log_path=misc.get_log_dir(), stream_level=args['verbose'])

    # show preamble
    preamble()

    logger.debug('command line arguments:')
    logger.debug(pprint.pformat(args))

    if andeshelp(**args) or search(**args) or edit_conf(**args) or remove_output(**args) \
            or save_config(**args):
        return

    # process input files
    if len(args['filename']) == 0:
        logger.info('error: no input file. Try \'andes -h\' for help.')

    # preprocess cli args
    path = args.get('input_path', os.getcwd())
    ncpu = args['ncpu']
    if ncpu == 0 or ncpu > os.cpu_count():
        ncpu = os.cpu_count()

    cases = []

    for file in args['filename']:
        # use absolute path for cases which will be respected by FileMan
        full_paths = os.path.abspath(os.path.join(path, file))
        found = glob.glob(full_paths)
        if len(found) == 0:
            logger.info('error: file {} does not exist.'.format(full_paths))
        else:
            cases += found

    # remove folders and make cases unique
    cases = list(set(cases))
    valid_cases = []
    for case in cases:
        if os.path.isfile(case):
            valid_cases.append(case)

    logger.debug('Found files: ' + pprint.pformat(valid_cases))

    if len(valid_cases) <= 0:
        pass
    elif len(valid_cases) == 1:
        run(valid_cases[0], **args)
    else:
        # set verbose level for multi processing
        logger.info('Processing {} jobs on {} CPUs'.format(len(valid_cases), ncpu))
        logger.handlers[1].setLevel(logging.WARNING)

        # start processes
        jobs = []
        for idx, file in enumerate(valid_cases):
            args['pid'] = idx
            job = Process(
                name='Process {0:d}'.format(idx),
                target=run,
                args=(file, ),
                kwargs=args)
            jobs.append(job)
            job.start()

            start_msg = 'Process {:d} <{:s}> started.'.format(idx, file)
            print(start_msg)
            logger.debug(start_msg)

            if (idx % ncpu == ncpu - 1) or (idx == len(valid_cases) - 1):
                sleep(0.1)
                for job in jobs:
                    job.join()
                jobs = []

        # restore command line output when all jobs are done
        logger.handlers[1].setLevel(logging.INFO)

    t0, s0 = elapsed(t0)

    if len(valid_cases) == 1:
        logger.info('-> Single process finished in {:s}.'.format(s0))
    elif len(valid_cases) >= 2:
        logger.info('-> Multiple processes finished in {:s}.'.format(s0))

    return
def main ( ) : t0 , s = elapsed ( ) args = vars ( cli_new ( ) ) config_logger ( log_path = misc . get_log_dir ( ) , stream_level = args [ 'verbose' ] ) preamble ( ) logger . debug ( 'command line arguments:' ) logger . debug ( pprint . pformat ( args ) ) if andeshelp ( ** args ) or search ( ** args ) or edit_conf ( ** args ) or remove_output ( ** args ) or save_config ( ** args ) : return if len ( args [ 'filename' ] ) == 0 : logger . info ( 'error: no input file. Try \'andes -h\' for help.' ) path = args . get ( 'input_path' , os . getcwd ( ) ) ncpu = args [ 'ncpu' ] if ncpu == 0 or ncpu > os . cpu_count ( ) : ncpu = os . cpu_count ( ) cases = [ ] for file in args [ 'filename' ] : full_paths = os . path . abspath ( os . path . join ( path , file ) ) found = glob . glob ( full_paths ) if len ( found ) == 0 : logger . info ( 'error: file {} does not exist.' . format ( full_paths ) ) else : cases += found cases = list ( set ( cases ) ) valid_cases = [ ] for case in cases : if os . path . isfile ( case ) : valid_cases . append ( case ) logger . debug ( 'Found files: ' + pprint . pformat ( valid_cases ) ) if len ( valid_cases ) <= 0 : pass elif len ( valid_cases ) == 1 : run ( valid_cases [ 0 ] , ** args ) else : logger . info ( 'Processing {} jobs on {} CPUs' . format ( len ( valid_cases ) , ncpu ) ) logger . handlers [ 1 ] . setLevel ( logging . WARNING ) jobs = [ ] for idx , file in enumerate ( valid_cases ) : args [ 'pid' ] = idx job = Process ( name = 'Process {0:d}' . format ( idx ) , target = run , args = ( file , ) , kwargs = args ) jobs . append ( job ) job . start ( ) start_msg = 'Process {:d} <{:s}> started.' . format ( idx , file ) print ( start_msg ) logger . debug ( start_msg ) if ( idx % ncpu == ncpu - 1 ) or ( idx == len ( valid_cases ) - 1 ) : sleep ( 0.1 ) for job in jobs : job . join ( ) jobs = [ ] logger . handlers [ 1 ] . setLevel ( logging . INFO ) t0 , s0 = elapsed ( t0 ) if len ( valid_cases ) == 1 : logger . info ( '-> Single process finished in {:s}.' . format ( s0 ) ) elif len ( valid_cases ) >= 2 : logger . info ( '-> Multiple processes finished in {:s}.' . format ( s0 ) ) return
The main function of the Andes command-line tool.

    This function executes the following workflow:

     * Parse the command line inputs
     * Show the tool preamble
     * Output the requested helps, edit/save configs or remove outputs. Exit
       the main program if any of the above is executed
     * Process the input files and call ``main.run()`` using single- or
       multi-processing
     * Show the execution time and exit

    Returns
    -------
    None