0

I'm working on something where I need to use argparse. Here's the code I got a problem with:

parser = argparse.ArgumentParser()
parser.add_argument('--create n file', dest='create',
                    nargs=2, default=(1, 'world1.json'),
                    help='Create a party of n player with mission parameters in file')

I'm trying to find a way to either set both n and file to another value, or set only one of them. n is an int and file a str.

Here's what I would like to get, using the following command:

Command Expected result
python mission.py --create 2 create = [2, 'world1.json']
python mission.py --create world2.json create = [1, 'world2.json']
python mission.py --create 3 world2.json create = [3, 'world2.json']

When --create is used (with or without specifying n/file), I'll need to start a function using the list as arguments.

I've tried multiple things and read argparse documentation more than once but can't find a way to do it.

wovano
  • 4,543
  • 5
  • 22
  • 49
  • Change to `add_argument('--create', nargs='+')`. After parsing decide for yourself what to do with the 1 or more strings in the `args.create` list. `argparse` isn't set up decode a mix of int and str types. – hpaulj Nov 28 '17 at 03:46
  • Save yourself a lot of work, use the begins library. https://pypi.python.org/pypi/begins/0.9 – SteveJ Nov 28 '17 at 05:09
  • @stevej, How does `begins` help with this spec? How do you express this requirement as a function's arguments? – hpaulj Nov 28 '17 at 05:24
  • On further thought, I think I can come up with a custom `type` function and `Action` class that does what you want, even replacing default values piecemeal. But it will be just as easy to do that conversion after parsing. Why don't you do that, and I can then suggest how to make it a part of the parser? – hpaulj Nov 28 '17 at 07:49
  • Edited my question to add what my goal is using --create. @hpaulj using `nargs='+'` doesn't work for what i need. Since user could just use `--create` alone to make a party using the default list [1, 'world1.json]. After that what you suggest me to do is to just decode the list after? – Fabien Bauer Nov 28 '17 at 14:42

1 Answers1

1

The code below returns the expected results for the listed usecases. I decided to use an extra function to handle the argument, as the program must accept either an int or a string for the first argument passed.

I use a "try" block to see whether the single argument can be parsed as an int before proceeding.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--create n file', dest='create', nargs='+', default=(1,'world1.json'),
                    help='Create a party of n player with mission parameters in file')
args = parser.parse_args()

def get_n_file(arg):
    if len(arg)==1:
        try:
            i = int(arg[0])
            result = int(arg[0]), 'world'+str(arg[0])+'.json'
        except:
            s = arg[0]
            result = 1, s
        return result
    elif len(arg)==2:
        return int(arg[0]), arg[1]

print(args.create)

n, f = get_n_file(args.create)

print(n, f)
Pierre de Buyl
  • 7,074
  • 2
  • 16
  • 22
  • You should [never use a bare except](https://stackoverflow.com/q/54948548/10669875). This should probably be `except ValueError:`. – wovano Jun 11 '22 at 08:06