snippetpythonMinor
Parse a config-file and add to command-line-arguments using argparse in Python
Viewed 0 times
fileargumentsargparselineparseconfigusingpythonandcommand
Problem
I am trying to parse the command line arguments using argparse, and if the user specifies a yaml file for the config-file, add those arguments to the args from argparse
If my config-file has the following data:
And I run my code like this:
I get this for the output:
So, it works, but is it good code?
import argparse
import yaml
from pprint import pprint
class CLI(object):
def execute(self):
self.create_parser()
self.options = self.parse_args()
pprint(self.options)
def create_parser(self):
self.parser = argparse.ArgumentParser()
g = self.parser.add_argument_group('Device Targets')
g.add_argument(
'--config-file',
dest='config_file',
type=argparse.FileType(mode='r'))
g.add_argument('--name', default=[], action='append')
g.add_argument('--age', default=[], action='append')
g.add_argument('--delay', type=int)
g.add_argument('--stupid', dest='stupid', default=False, action='store_true')
def parse_args(self):
args = self.parser.parse_args()
if args.config_file:
data = yaml.load(args.config_file)
delattr(args, 'config_file')
for key, value in data.items():
if isinstance(value, list):
for v in value:
getattr(args, key, []).append(v)
else:
setattr(args, key, value)
return args
cli = CLI()
cli.execute()If my config-file has the following data:
name: [Jill, Bob]
age: [21, 33]
delay: 30And I run my code like this:
python test.py --conf args.txt --name 'Mark'I get this for the output:
Namespace(age=[21, 33], delay=30, name=['Mark', 'Jill', 'Bob'], stupid=False)So, it works, but is it good code?
Solution
You don't need a class
In your current version of the code, it is hard to see what is stored in an instance and how the data flows around the different methods. If you do write a class, I find it clearer to have an init to define the different members but in your case, you could stop writing classes.
Removing the class, you get something like :
The name
The right tool for the job
To add all the content from
In your current version of the code, it is hard to see what is stored in an instance and how the data flows around the different methods. If you do write a class, I find it clearer to have an init to define the different members but in your case, you could stop writing classes.
Removing the class, you get something like :
def execute():
pprint(parse_args(create_parser()))
def create_parser():
parser = argparse.ArgumentParser()
g = parser.add_argument_group('Device Targets')
g.add_argument(
'--config-file',
dest='config_file',
type=argparse.FileType(mode='r'))
g.add_argument('--name', default=[], action='append')
g.add_argument('--age', default=[], action='append')
g.add_argument('--delay', type=int)
g.add_argument('--stupid', dest='stupid', default=False, action='store_true')
return parser
def parse_args(parser):
args = parser.parse_args()
if args.config_file:
data = yaml.load(args.config_file)
delattr(args, 'config_file')
arg_dict = args.__dict__
for key, value in data.items():
if isinstance(value, list):
for v in value:
arg_dict[key].append(v)
else:
arg_dict[key] = value
return args
execute()The name
execute probably needs to be improved for something more meaningful.The right tool for the job
To add all the content from
value to arg_dict[key], you shouldn't use àppend but extend.if isinstance(value, list):
arg_dict[key].extend(value)
else:
arg_dict[key] = valueCode Snippets
def execute():
pprint(parse_args(create_parser()))
def create_parser():
parser = argparse.ArgumentParser()
g = parser.add_argument_group('Device Targets')
g.add_argument(
'--config-file',
dest='config_file',
type=argparse.FileType(mode='r'))
g.add_argument('--name', default=[], action='append')
g.add_argument('--age', default=[], action='append')
g.add_argument('--delay', type=int)
g.add_argument('--stupid', dest='stupid', default=False, action='store_true')
return parser
def parse_args(parser):
args = parser.parse_args()
if args.config_file:
data = yaml.load(args.config_file)
delattr(args, 'config_file')
arg_dict = args.__dict__
for key, value in data.items():
if isinstance(value, list):
for v in value:
arg_dict[key].append(v)
else:
arg_dict[key] = value
return args
execute()if isinstance(value, list):
arg_dict[key].extend(value)
else:
arg_dict[key] = valueContext
StackExchange Code Review Q#79008, answer score: 9
Revisions (0)
No revisions yet.