Rob Oakes
Feb 01, 2022

Python Snippets: Splitting CSV lists in argparse

argparse is a powerful library for building command line interfaces in Python. Unfortunately, it lacks support for common inputs. In this post we show how they can be implemented using a custom type.

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.

Rob Oakes Feb 01, 2022
More Articles by Rob Oakes

Loading

Unable to find related content

Comments

Loading
Unable to retrieve data due to an error
Retry
No results found
Back to All Comments