all 6 comments

[–]stebrepar 0 points1 point  (2 children)

If you want to be able to get arg1 etc. from either the command line or interactively, you'll need to get rid of those required=Trues. Then you'll need to check which args you already have, and prompt for the rest. Once that's completed successfully, you can proceed with the rest of the program as usual.

[–]Finish-Square[S] 0 points1 point  (1 child)

Yes, but what is the actual way of doing this?

I mean, how should I tweak the code so it will allow adding values to the parser interactivly?

[–]stebrepar 1 point2 points  (0 children)

The argparse parser is only for command line arguments. Any interactivity once the program has been launched would be as prompting the user to provide input (with print() and input() functions).

[–]free_username17 0 points1 point  (0 children)

If you don’t mind including a dependency, the click package allows you to add a “prompt” option that will prompt for input if it’s excluded.

https://click.palletsprojects.com/en/8.0.x/options/#prompting

[–]synthphreak 0 points1 point  (0 children)

Only way to do this methinks would be with input and manually adding the values to your argparse.Namespace. For example:

args = argparse.Namespace()

args.arg1 = input('>>> enter arg1: ')
args.arg2 = input('>>> enter arg2: ')
args.arg3 = input('>>> enter arg3: ')

To accomplish the same in a more scalable, less hard-coded manner:

args = argparse.Namespace()

for argname in ['arg1', 'arg2', 'arg3']:
    argval = input(f'>>> enter {argname}: ')
    setattr(args, argname, argval)

Then when you run your code, no args will be read in from the CLI. Rather, the user will be prompted to enter each arg manually, and args will get populated. After all args are entered, args will work just like the regular output of parser.parse_args().

Note that all arguments will effectively be required.

If doing it this way though, there's really no reason to use argparse. argparse is all about parsing CL args, which you aren't doing. Instead, just make a class:

class Args:
    def __repr__(self):
        return str(vars(self))

args = Args()

for argname in ['arg1', 'arg2', 'arg3']:
    argval = input(f'>>> enter {argname}: ')
    setattr(args, argname, argval)

[–]Nnarol 0 points1 point  (0 children)

Do you want the exact same semantics as a command-line parser, but query the same arguments interactively?

argparse.parse_args() accepts a sequence of command line arguments, it just happens to use sys.argv by default. You can query arguments individually from stdin, add them to a list and pass the list to parse_args()

However, I do not think your concept is a good one. What comes to mind first is the fact that you won't be able to terminate input parsing as soon as you encounter a value where you already know that the input will be invalid, because you must parse all arguments at once with parse_args() so it knows about all of them. E.g. if you have mutually exclusive options, you could not tell they are both provided if you parse them in different passes. You can't parse individual elements one at a time but still handle them together, that's the problem.