I'm writing a tool with argparse that'll take a list of source directories from the command line and process all the files in them. Ultimately, when parse_args is called, each directory is scanned for files to process, and the list of files is put into the files attribute off the returned namespace.
parser = argparse.ArgumentParser()
parser.add_argument('-s', '--sources'
, dest = 'files'
, default = 'results/e1653a3'
, nargs = '*'
, metavar = 'SOURCE'
, action = ConcatAction
, type = FileList
)
args = parser.parse_args()
Here, the FileList function takes a directory name and returns a list of files. ConcatAction is an action which flattens a list of lists. The result is that I can call my tool like tool.py -s dir1 dir2, and args.files contains all the files in both directories.
By default, I want it to scan multiple directories; however, passing a list to the defaults:
, default = ['dir1', 'dir2']
Sidesteps the type conversion system of argparse, so FileList() is never called, and args.files contains the list ['dir1', 'dir2'], and not the scanned files. If I try
, default = 'dir1 dir2'
Then a single call to FileList('dir1 dir2') is made instead of the two calls FileList('dir1') FileList('dir2')
I know I can just process the source directories outside of argparse to get the functionality I want, but is there anyway to get argparse to perform type conversion on a list of default values?
As you note, a string default is passed through the type function, while all other defaults are simply assigned to the attribute (unchanged). I think the solution is to build the exact file list that you want to see in the Namespace in the default case.
parser.add_argument('-s', '--sources'
, dest = 'files'
, default = [FileList('dir1'), FileList('dir2')] # exact file list
, nargs = '*'
, metavar = 'SOURCE'
, action = ConcatAction
, type = FileList
)
I'll let you worry about applying that flattening action.
Or you could initialize a Namespace with the desired file list. In this case the default is ignored.
ns = argparse.NameSpace(files = [FileList('dir1'), FileList('dir2')])
# or
ns = argparse.NameSpace(files = ['dir1/file1','dir1/file2','dir2/file1',...])
parser.parse_args(sys.argv, namespace=ns)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With