We define argument lists with a name that has no - decoration and a piece of advice in the nargs= parameter. If the rule is one or more argument values, we specify nargs="+". If the rule is zero or more argument values, we specify nargs="*", as shown in the following code. If the rule is optional, we specify nargs="?". This will collect all other argument values into a single sequence in the resulting namespace:
parser.add_argument(
"filenames", action="store", nargs="*", metavar="file...")
When the list of filenames is optional, it generally means that STDIN or STDOUT will be used if no specific filenames are provided.
If we specify a nargs= value, then the result becomes a list. If we specify nargs=1, then the resulting object is a one-element list; this generalizes nicely if we need to change to nargs='+'. As a special case, omitting nargs, leads to a result that is a single value; this does not generalize well.
Creating a list (even if it has only one element) is handy because we might want to process the arguments in the following manner:
for filename in config.filenames: process(filename)
In some cases, we may want to provide a sequence of input files that includes STDIN. The common convention for this is a filename of - as an argument. We'll have to handle this within our application with something like the following code:
for filename in config.filenames: if filename == '-': process(sys.stdin) else: with open(filename) as input: process(input)
This shows us a loop that will attempt to handle a number of filenames, potentially including - to show when to process standard input among a list of files. A try: block should probably be used around the with statement.