Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python argparse: type conversion of a list of default arguments

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?

like image 272
Cookyt Avatar asked Feb 13 '26 20:02

Cookyt


1 Answers

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)
like image 185
hpaulj Avatar answered Feb 15 '26 09:02

hpaulj



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!