Python Snippets: Splitting CSV lists in argparse
The argparse
module in Python makes it very easy to create command-line interfaces. With a minimal amount of code, you can quickly build a robust script that is capable of taking input parameters, convert them to a specific type (float
, int
, datetime
, and many more are supported), validate that the input parameters are correct, and produce a single container with the values that can be passed into your program for processing.
Example Program: Process a Set of Numbers
Consider the example below (stolen from the argparse
documentation), which takes a list of integers and produces either the sum or the max. Example usage:
process-int.py --sum 1 2 3 4
import argparse parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument('integers', metavar='N', type=int, nargs='+', help='an integer for the accumulator') parser.add_argument('--sum', dest='accumulate', action='store_const', const=sum, default=max, help='sum the integers (default: find the max)') args = parser.parse_args() print(args.accumulate(args.integers))
Implementing Custom Input Types
Despite its power, however, argparse
has limitations. One of those is lack of support for splitting comma separated input into an array or other type of iterable. While using one of the other option types and creating the container isn't difficult, it's one of those things that you would think the API would support, right?
Fortunately, adding support for comma separated lists is pretty straightforward using the type
option of parser.add_argument
. The code listing below shows how you might implement a variant number processing script which accepts an --integers
argument with comma separated numeric values. Example command line usage:
process-int.py --integers 1,2,3,4 --sum
import argparse from argparse import ArgumentError def csv_float(vstr, sep=','): ''' Convert a string of comma separated values to floats @returns iterable of floats ''' values = [] for v0 in vstr.split(sep): try: v = float(v0) values.append(v) except ValueError as err: raise ArgumentError('Invalid value %s, values must be a number' % v) return values parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument('--sum', dest='accumulate', action='store_const', const=sum, default=max, help='sum the integers (default: find the max)') parser.add_argument('--integers', dest='integers', type=csv_float, required=True, help='a comma separated list of integers for the accumulator. Example: 1,2,3,4.') args = parser.parse_args() print(args.accumulate(args.integers))
Note the use of ArgumentError
in the csv_float
method. By catching values that can't be converted and raising the argument error class instead, we are able to integrate with the error management system and provide feedback to the user that they have entered an invalid type.
Comments
Loading
No results found