0

I am writing a program which processes all files in a predefined folder. Optionally, it shall process only certain specified files in a specified folder. For this I want to use an optional command line parameter -s or --specify-files.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-s", "--specify-files", type=str, metavar="FOLDER FILES", nargs="+", 
        help="Will process specified FILES in specified FOLDER. Specify at least one file. Folder path and each file name must be separated by space")
args = parser.parse_args("-s ~/custom/folder file1.txt file2.txt file34.txt".split())
print(args)

Output:

Namespace(select_files=['~/custom/folder', 'file1.txt', 'file2.txt', 'file34.txt'])

From here the program knows that args.select_files[0] is the folder path and args.select_files[1:] is a list of files to process.

Thanks to nargs="+" the ArgumentParser warns if the user does not specify anything, but I wonder how I could error out and warn the user if he enters less than two arguments:

args = parser.parse_args("-s ~/custom/folder".split())

Current Output:

Namespace(specify_files=['~/custom/folder'])

Expected:

usage: minimal.py [-h] [-s [FOLDER FILES ...]]
minimal.py: error: argument -s/--specify-files: expected at least two arguments

For my program, anythin less than two arguments for -s does not make sense. I could easily write a check for this and raise an error after parser has parsed the arguments, but I'd prefer if the error would already be raised before parser.parse_args outputs the Namespace object. Something like a nargs="2+" would be convenient here, if you know what I mean.

fleetingbytes
  • 2,512
  • 5
  • 16
  • 27
  • It isn't directly possible the way you're describing it. However, there is a workaround in the following link which addresses your concern. https://stackoverflow.com/questions/8411218/can-argparse-in-python-2-7-be-told-to-require-a-minimum-of-two-arguments – Rohit Kewalramani Oct 28 '20 at 05:14
  • 2
    The suggested link works for positionals, but not for one optional (flagged). But since the first string is distinct, a path, you might still want to put it in a separate argument. Otherwise doing your own checking after parsing is perfectly fine. `parser.error(...)` lets you use the same `argparse` format. The Python gods will not punish you for doing this! – hpaulj Oct 28 '20 at 07:19
  • 1
    Thank you @hpaulj. I'll look into the parser.error() thing and implement my own check for this case. I hesitate to have the folder path parsed as an independent argument, because there is no way to enforce that two optional arguments must co-occur (optional argument for folder path would have to co-occur with the optional argument for the files). One can only enforce that two arguments exclude each other. – fleetingbytes Oct 28 '20 at 11:53

0 Answers0