-1

In python I have:

parser = argparse.ArgumentParser(description='RANGES')
parser.add_argument('IP_Address', action='store', type=str)

How can I let the user provide a single IP adresses or range or separate data?

for example I want to support:

python3 main.py 1.1.1.1
python3 main.py 1.1.1.1, 2.2.2.2
python3 main.py 1.1.1.1-2.2.2.2

Where the first iterates over 1.1.1.1 only, the second iterates over 1.1.1.1 and 2.2.2.2. While the latter iterates over all ips in the specified range.

3
  • You'll simply have to parse the entered string later…? Commented Jul 7, 2022 at 9:51
  • @deceze I remember there is a simplier approach, for example what if I want to support only multiple values and not ranges? Commented Jul 7, 2022 at 9:59
  • 1
    You can use nargs to accept multiple values, but that won't help you for the ranges case, which you still need to parse separately… Commented Jul 7, 2022 at 10:01

2 Answers 2

1

You could try something like this:

parser.add_argument('IP_Address', nargs='+', action='store', type=str)

This would only solve your first question.

nargs='*' might also be possible although does not seem like it from your use case

For the second, you need to specify the rules of the range creation.

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

Comments

0

A slightly more complex solution is to define a function for the type attribute and a class extending argparse._AppendAction. The idea of this class is to 'flatten' internally the argument list. This is a job that can also be done after parsing (in this case, no need to extend the class).

import argparse
import re

class newAppendAction(argparse._AppendAction):
    def __call__(self, parser, namespace, values, option_string=None):
        items = getattr(namespace, self.dest, None)
        items = argparse._copy_items(items)
        for value in values:
            if type(value) is list:
                for item in value:
                    items.append(item)
            else:
                items.append(value)
        setattr(namespace, self.dest, items)

def type_lambda(value):
    return [v for v in re.split("\-|\,", value) if len(v) > 0]

We can then simply declare the argument of the parser:

parser = argparse.ArgumentParser(description='RANGES')
parser.add_argument('IP_Address', nargs='+', action=newAppendAction, type=type_lambda)

And test the result:

>>> s3 = "python3 main.py 1.1.1.1-2.2.2.2"
>>> print(parser.parse_args(s1.split(" ")[2:]))
Namespace(IP_Address=['1.1.1.1'])

>>> s2 = "python3 main.py 1.1.1.1, 2.2.2.2"
>>> print(parser.parse_args(s2.split(" ")[2:]))
Namespace(IP_Address=['1.1.1.1', '2.2.2.2'])

>>> s1 = "python3 main.py 1.1.1.1"
>>> print(parser.parse_args(s3.split(" ")[2:]))
Namespace(IP_Address=['1.1.1.1', '2.2.2.2'])

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.