2

I am looking for a way to parse the following commandline syntax using the argparse module in python3:

myapp.py [folder] [[from] to]

Meaning: The user may optionally define a folder, which defaults to cwd. Additionally the user may pass up to two integers. If only one number is given, it should be stored in the to variable. This is similar to the syntax of the python builtin range().

e.g.:

myapp.py folder
myapp.py 10
myapp.py 5 10
myapp.py folder 5 10
myapp.py folder 10

Is that possible? If so, how?

1
  • 2
    How is argparse supposed to differentiate between myapp folder and myapp 10? As far as I see it, you don't have much of a choice other than to post-process the returned namespace -- At which point, you might as well just process sys.argv Commented Oct 18, 2012 at 18:50

4 Answers 4

2

Use options; that's what they're there for (and what argparse is good at parsing).

Thus, a syntax like

myapp.py [-F folder] [[from] to]

would make a lot more sense, and be easier to parse.

Sign up to request clarification or add additional context in comments.

Comments

1

You can do something quite silly:

import argparse
import os

class MyAction(argparse.Action):
    def __call__(self,parser,namespace,values,option_string=None):
        namespace.numbers = []
        namespace.path = os.getcwd()
        for v in values:
            if os.path.isdir(v):
                namespace.path = v
            else:
                try:
                    namespace.numbers.append(int(v))
                    if len(namespace.numbers) > 2
                       parser.error("Barg2!!!")
                except ValueError:
                    parser.error("Barg!!!")

p = argparse.ArgumentParser()
p.add_argument('stuff',nargs='*',action=MyAction)
n = p.parse_args()
print n

But if you're going to do this, you might as well just process sys.argv yourself -- you should really consider using actual options here...

1 Comment

holy sh** ... awesome answer, but I will follow your sys.argv advice
0

I'd also suggest parsing sys.argv yourself.

FWIW, I parse sys.argv even on projects where argparse or similar would work, because parsing sys.argv yourself plays nicely with pylint or flake8.

Comments

0

I couldn't see a way to do it without using a named argument for folder:

# usage: argparsetest2.py [-h] [--folder [FOLDER]] [to] [fr]

import argparse
import os

parser = argparse.ArgumentParser()
parser.add_argument('--folder', dest='folder', nargs='?', default=os.getcwd())
parser.add_argument('to', type=int, nargs='?')
parser.add_argument('fr', type=int, nargs='?')
args = parser.parse_args()

print args

2 Comments

that would be [to] [from], not [[from] to]
@FabianHenze I think thats the only way to get the positional behavior you wanted. If you revers the order, then a single integer gets assigned to 'from' instead of 'to'. The only other option (for argparse anyway) is to use all named arguments, e.g myapp.py --folder <folder> -- from <from> --to <to>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.