Command Line Parser ------ argparse vs docopt
Overall, argparse is easier to use, and can accommodate different argument data types. However, it is tricky when the number of positional arguments varies.
docopt can deal with flexible number and combinations of positional arguments. However, it cannot set data types directly.
An argparse module example in exampleArgparse.py
import argparse
import math
def squareopt(args):
print('The power of {} is {}'.format(args.inputNum,(args.inputNum)**2))
def squarerootopt(args):
print('The square root of {} is {}'.format(args.inputNum,math.sqrt(args.inputNum)))
commands = {
'squareopt': squareopt,
'squarerootopt': squarerootopt
}
parser = argparse.ArgumentParser(description='Test of argparse module')
# positional arguments
parser.add_argument("operation", help="The operation you want")
parser.add_argument("inputNum", help="The number to be operated",type=int)
# optional arguments
parser.add_argument('--echo', default='', help="The string to be printed")
parser.add_argument('--epochs', default=100, type=int, help="Number of epochs")
parser.add_argument('-r', '--routings', default=3, type=int, help="Number of iterations, should > 0")
parser.add_argument('-z', '--zebra', default=3, type=int, help="Number of zebras, should > 0")
parser.add_argument('--train', default=0, type=int, help="trainmode 0: train 1: test")
parser.add_argument('--save_dir', default='./result', help="Directory to save the results")
parser.add_argument('--lr', default=0.001, type=float, help="Initial learning rate")
if __name__ == '__main__':
args = parser.parse_args()
print(args)
print(args.echo)
print(args.epochs)
func = commands[args.operation]
func(args)
And from the terminal:
% python3 exampleArgparse.py --help
usage: exampleArgparse.py [-h] [--echo ECHO] [--epochs EPOCHS] [-r ROUTINGS]
[-z ZEBRA] [--train TRAIN] [--save_dir SAVE_DIR]
[--lr LR]
operation inputNum
Test of argparse module
positional arguments:
operation The operation you want
inputNum The number to be operated
optional arguments:
-h, --help show this help message and exit
--echo ECHO The string to be printed
--epochs EPOCHS Number of epochs
-r ROUTINGS, --routings ROUTINGS
Number of iterations, should > 0
-z ZEBRA, --zebra ZEBRA
Number of zebras, should > 0
--train TRAIN trainmode 0: train 1: test
--save_dir SAVE_DIR Directory to save the results
--lr LR Initial learning rate
% python3 exampleArgparse.py squareopt 4 --echo="long long long time ago" --epochs=500
Namespace(echo='long long long time ago', epochs=500, inputNum=4, lr=0.001, operation='squareopt', routings=3, save_dir='./result', train=0, zebra=3)
long long long time ago
500
The power of 4 is 16
A docopt module example in exampleDocopt.py
"""
Usage:
exampleDocopt.py [options] (-h | --help)
exampleDocopt.py singleNum [options] <operation> <inputNum>
exampleDocopt.py doubleNum [options] <operation2> <inputNum1> <inputNum2>
exampleDocopt.py [options] <operation2> <inputNum1> <inputNum2>
Options:
-h --help show this help message and exit
-v,--verbose show debugging messages
--echo ECHO The string to be printed [default: The string to be printed]
--epochs EPOCHS Number of epochs [default: 100]
-r ROUTINGS, --routings ROUTINGS
Number of iterations, should > 0 [default: 3]
-z=ZEBRA --zebra=ZEBRA
Number of zebras, should > 0 [default: 3]
--train TRAIN [default: 0] trainmode 0: train 1: test
--save_dir SAVE_DIR Directory to save the results [default: ./result]
--lr LR Initial learning rate [default: 0.001]
"""
from docopt import docopt
import math
def squareopt(args):
print('The power of {} is {}'.format(args['<inputNum>'],(float(args['<inputNum>']))**2))
def squarerootopt(args):
print('The square root of {} is {}'.format(args['<inputNum>'],math.sqrt(float(args['<inputNum>']))))
commands = {
'squareopt': squareopt,
'squarerootopt': squarerootopt
}
def plus(args):
print('The sum of {} and {} is {}'.format(args['<inputNum1>'],args['<inputNum2>'], float(args['<inputNum1>'])+float(args['<inputNum2>']) ))
def minus(args):
print('The differnce between {} and {} is {}'.format(args['<inputNum1>'],args['<inputNum2>'], float(args['<inputNum1>'])-float(args['<inputNum2>']) ))
commands2 = {
'plus': plus,
'minus': minus
}
if __name__ == '__main__':
arguments = docopt(__doc__)
print(arguments)
print(arguments['--echo'])
print(arguments['--epochs'])
if arguments['<operation>'] is not None:
func = commands[arguments['<operation>']]
func(arguments)
if arguments['<operation2>'] is not None:
func = commands2[arguments['<operation2>']]
func(arguments)
And from the terminal:
% python3 exampleDocopt.py --help
Usage:
exampleDocopt.py [options] (-h | --help)
exampleDocopt.py singleNum [options] <operation> <inputNum>
exampleDocopt.py doubleNum [options] <operation2> <inputNum1> <inputNum2>
exampleDocopt.py [options] <operation2> <inputNum1> <inputNum2>
Options:
-h --help show this help message and exit
-v,--verbose show debugging messages
--echo ECHO The string to be printed [default: The string to be printed]
--epochs EPOCHS Number of epochs [default: 100]
-r ROUTINGS, --routings ROUTINGS
Number of iterations, should > 0 [default: 3]
-z=ZEBRA --zebra=ZEBRA
Number of zebras, should > 0 [default: 3]
--train TRAIN [default: 0] trainmode 0: train 1: test
--save_dir SAVE_DIR Directory to save the results [default: ./result]
--lr LR Initial learning rate [default: 0.001]
% python3 exampleDocopt.py singleNum --echo="long long long time ago" --epochs=500 squareopt 4
{'--echo': 'long long long time ago',
'--epochs': '500',
'--help': False,
'--lr': '0.001',
'--routings': '3',
'--save_dir': './result',
'--train': '0',
'--verbose': False,
'--zebra': '3',
'<inputNum1>': None,
'<inputNum2>': None,
'<inputNum>': '4',
'<operation2>': None,
'<operation>': 'squareopt',
'doubleNum': False,
'singleNum': True}
long long long time ago
500
The power of 4 is 16.0
% python3 exampleDocopt.py --echo="long long long time ago" --epochs=500 plus 3 4
{'--echo': 'long long long time ago',
'--epochs': '500',
'--help': False,
'--lr': '0.001',
'--routings': '3',
'--save_dir': './result',
'--train': '0',
'--verbose': False,
'--zebra': '3',
'<inputNum1>': '3',
'<inputNum2>': '4',
'<inputNum>': None,
'<operation2>': 'plus',
'<operation>': None,
'doubleNum': False,
'singleNum': False}
long long long time ago
500
The sum of 3 and 4 is 7.0