Python argparse: Complex Argument Parsing Scenario

malenkiy_scot

I would like to implement the following command line arguments parsing scenario:

I have 4 arguments: -g, -wid, -w1, and -w2.

-w1 and -w2 always appear together

-wid and (-w1 -w2) are mutually exclusive, but one or the other is required

-g is optional; if it is not specified only (-w1 -w2) can appear, but not -wid

Is there an elegant way to implement this using argparse, but without sub-commands (I am already in a sub-command)?

I was thinking of custom actions, but then in the body of the action I'd need to know when it is called for the last time (i.e. when the last argument is being parsed), which I do not know how to do since the number and the order of the arguments may vary.

Some more explanation just in case: the tool I am writing creates a gadget using a widget and a gadget parameter -g. The widget is either an existing widget - and then it is referred to by its id -wid, or a new widget that is created using parameters -w1 and -w2. If -g is not specified then the tool will just create and store a new widget using (-w1 -w2) without creating the gadget.

Thank you in advance.

hpaulj

If you choose your defaults correctly, you can easily test for logical combinations of the argument values in the 'namespace' after 'parse_args'. You can also issue a parser error at that time. There is a bug report asking for mutually inclusive groups. There I suggest a mechanism for adding generalized combination testing. But it still requires your own logical tests.

http://bugs.python.org/issue11588 Add "necessarily inclusive" groups to argparse

The key to the solution I propose in that issue is making a seen_non_default_actions variable available to the programmer. This is a list (set actually) of actions which have been seen (taking into account that optional-positionals are always 'seen'). I would like to see more discussion of how implement a mixture of inclusive and exclusive groupings.

You specify:

I have 4 arguments: -g, -wid, -w1, and -w2. -w1 and -w2 always appear together -wid and (-w1 -w2) are mutually exclusive, but one or the other is required -g is optional; if it is not specified only (-w1 -w2) can appear, but not -wid

Which I would attempt to summarize as:

complex_group('g', required_next_exclusive_group('wid', inclusive_group('w1','w2)))

w1,w2 could be replaced with a '--w1w2',nargs=2. A simple 'mutually_inclusive_group' would work here. But argparse cannot handle nested groups.

wid and w1w2 could be put in a required mutually_exclusive_group.

-g requires a test like if args.g is None and args.wid is None: error()


Here's a script which behaves as you require (I think), using my latest patch in Issue11588. act_w1 etc are the actual action objects, which may appear in the seen_actions list. The test functions are registered with the subparser, and performed near the end of its parse_know_args().

parser = argparse.ArgumentParser(usage='custom usage')
sp = parser.add_subparsers(dest='cmd')
sp.required = True
spp = sp.add_parser('cmd1')
act_g = spp.add_argument('-g')
act_wid = spp.add_argument('--wid')
act_w1 = spp.add_argument('--w1')
act_w2 = spp.add_argument('--w2')

@spp.crosstest # decorator to register this function with spp
def test1(spp, seen_actions, *args):
    # seen_actions - list of actions that were seen by parser
    if 1==len({act_w1, act_w2}.intersection(seen_actions)):
        # error if only one of these was seen
        parser.error('-w1 and -w2 always appear together')
@spp.crosstest
def test2(spp, seen_actions, *args):
    # required mutually exclusive wid and (w1,w2 group)
    if act_wid in seen_actions:
        if act_w1 in seen_actions or act_w2 in seen_actions:
            parser.error('-wid and (-w1 -w2) are mutually exclusive')
    elif act_w1 not in seen_actions:
        parser.error('wid or (w1 and w2) required')
@spp.crosstest
def test3(spp, seen_actions, *args):
    # is this the simplest logical way of expressing this?
    if act_g not in seen_actions and act_wid in seen_actions:
        parser.error('not g, so not wid')
args = parser.parse_args()

In this example I save and test for the presence of the action objects. Testing could also be done using the dest strings. I'm exploring ways of making this testing more intuitive and user friendly. An expanded set of decorators seems most promising.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Understanding argument parsing with argparse in Python

From Dev

Argument parsing python using ArgParse

From Dev

Python: Solving a complex scenario analysis

From Dev

Parsing complex JSON with Python

From Dev

Parsing complex JSON with Python

From Dev

Reorder Python argparse argument groups

From Dev

Accessing argument values for argparse in Python

From Dev

Parsing Complex Mathematical Functions in Python

From Dev

python argparse stops parsing after it encounters '$'

From Dev

python argparse add_argument_group required

From Dev

Multiple files for one argument in argparse Python 2.7

From Dev

How to skip a positional argument in Python Argparse

From Dev

Use argparse module in python to parse a single argument

From Dev

python-argparse: assign a choice to each argument

From Dev

Python argparse: default argument stored as string, not list

From Dev

How to access a python argparse argument with a dot in the name

From Dev

Python argparse set 1 or more parameters to an argument

From Dev

How to access a python argparse argument with a dot in the name

From Dev

How to skip a positional argument in Python Argparse

From Dev

python argparse with mandatory input file argument

From Dev

Python argparse accept variable argument (even flags)

From Dev

Complex Regex scenario

From Dev

Elastic Search Complex Scenario

From Dev

ArgParse Python Module: Change default argument value for inherted argument

From Dev

Python: Parsing a complex string into usable data for analysis

From Dev

Parsing complex operands in boolean expressions in Python 2.7

From Dev

Python2.7 argparse.parse_known_args parsing incorrectly

From Dev

Python: Argument Parsing Validation Best Practices

From Dev

Python Assertion error during argument parsing

Related Related

  1. 1

    Understanding argument parsing with argparse in Python

  2. 2

    Argument parsing python using ArgParse

  3. 3

    Python: Solving a complex scenario analysis

  4. 4

    Parsing complex JSON with Python

  5. 5

    Parsing complex JSON with Python

  6. 6

    Reorder Python argparse argument groups

  7. 7

    Accessing argument values for argparse in Python

  8. 8

    Parsing Complex Mathematical Functions in Python

  9. 9

    python argparse stops parsing after it encounters '$'

  10. 10

    python argparse add_argument_group required

  11. 11

    Multiple files for one argument in argparse Python 2.7

  12. 12

    How to skip a positional argument in Python Argparse

  13. 13

    Use argparse module in python to parse a single argument

  14. 14

    python-argparse: assign a choice to each argument

  15. 15

    Python argparse: default argument stored as string, not list

  16. 16

    How to access a python argparse argument with a dot in the name

  17. 17

    Python argparse set 1 or more parameters to an argument

  18. 18

    How to access a python argparse argument with a dot in the name

  19. 19

    How to skip a positional argument in Python Argparse

  20. 20

    python argparse with mandatory input file argument

  21. 21

    Python argparse accept variable argument (even flags)

  22. 22

    Complex Regex scenario

  23. 23

    Elastic Search Complex Scenario

  24. 24

    ArgParse Python Module: Change default argument value for inherted argument

  25. 25

    Python: Parsing a complex string into usable data for analysis

  26. 26

    Parsing complex operands in boolean expressions in Python 2.7

  27. 27

    Python2.7 argparse.parse_known_args parsing incorrectly

  28. 28

    Python: Argument Parsing Validation Best Practices

  29. 29

    Python Assertion error during argument parsing

HotTag

Archive