Parsing arguments using argparse and mpi4py
Question: I want to run a Python script in several parallel processes under MPI, and I
need to pass command-line arguments. I'm using the argparse module in Python,
but it's a little messy sometimes. If I don't specify the right arguments, all
the processes complain, so I get many copies of the same error message.

I tried making only process 0 parse the arguments and then broadcast the
results to the other processes, but then the other processes hang when the
parsing fails and nothing gets broadcast.

How can I parse the command-line arguments, and print a readable message when
the parsing fails?


Answer: The extra piece I needed was to wrap a try/finally around the argument parsing
step in process 0. In the finally block, broadcast _something_ to the other
processes. If parsing failed, you will broadcast `None`, and they can all
silently exit.

    
    
    from mpi4py import MPI
    from time import sleep
    import argparse
    
    def parseOptions(comm):
        parser = argparse.ArgumentParser(
            description='Print some messages.')
    
        parser.add_argument('iteration_count', help='How many times', type=int)
        parser.add_argument('message',
                            help='What to say',
                            nargs=argparse.OPTIONAL,
                            default='Hello, World!')
    
        args = None
        try:
            if comm.Get_rank() == 0:
                args = parser.parse_args()
        finally:
            args = comm.bcast(args, root=0)
    
        if args is None:
            exit(0)
        return args
    
    def main():
        comm = MPI.COMM_WORLD  # @UndefinedVariable
        rank = comm.Get_rank()
        size = comm.Get_size()
    
        args = parseOptions(comm)
    
        if rank == 0:
            print args.message
    
        for i in range(args.iteration_count):
            if i%size == rank:
                print '{} in rank {} started.'.format(i, rank)
                sleep(.5)
                print '...'
                sleep(.5)
                print '{} in rank {} ended.'.format(i, rank)
    
    if __name__ == '__main__':
        main()
    

I run the code with a command like this:

    
    
    mpirun -np 4 python scratch.py 13
    

