Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can argparse associate positional arguments with named arguments?

I'd like to associate positional arguments with the "argument state" which exists when they occur. For example, the following command line:

script.py -m 1 foo -r 2 bar -r 7 baz -m 6 quux

Should produce the following associations:

foo:  m=1, r=0 (default value for r)
bar:  m=1, r=2
baz:  m=1, r=7
quux: m=6, r=7

Can this be done with the argparse module?

like image 969
Ben Blank Avatar asked Nov 13 '22 03:11

Ben Blank


1 Answers

This might not be useful to you, but this problem seems to be easiest if you can break sys.argv into pieces -- Essentially, you need to be able to figure out which pieces are supposed to be "positional" arguments (they're not actually positional since as you say, they can occur anywhere) and which pieces are supposed to be some sort of argument. In the example below, I've set it up to work with your example, but you could just as easily split sys.argv on files -- or on a certain kind of file. The condition function is up to you to write. The rest will (hopefully) be self-explanatory.

import argparse
import sys
import copy
import os

def split_list(lst,condition):
    current=[]
    out=[current]
    for arg in lst:
        current.append(arg)
        if(condition(arg)):
            current=[]
            out.append(current)

    return out


parser=argparse.ArgumentParser()
parser.add_argument('-m',action='store')
parser.add_argument('-r',default='0',action='store')
#pieces=split_list(sys.argv[1:],os.path.isfile)
pieces=split_list(sys.argv[1:],lambda x: x in ('foo','bar','baz','quux'))
options={} #use collections.OrderedDict if order matters -- or some more suitable data structure.
default=argparse.Namespace()
for args in pieces:
    if(not args):
        continue
    ns=copy.deepcopy(default)
    default=parser.parse_args(args[:-1],namespace=ns)
    options[args[-1]]=default

print (options)
like image 104
mgilson Avatar answered Dec 16 '22 10:12

mgilson