0
from argparse import ArgumentParser


class MainClass:
    @classmethod
    def main(cls):
        print("[Start of Main]")

        # initialize argument parser
        my_parser = ArgumentParser()
        my_parser.add_argument("-i", help="input directory", type=str)
        my_parser.add_argument("-o", help="output directory", type=str)

        my_group = my_parser.add_mutually_exclusive_group()
        my_group.add_argument("--txt", help="output as .txt files")
        my_group.add_argument("--rtf", help="output as .rtf files")

        # parse the argument
        args = my_parser.parse_args()

        if args.i is None:
            print("INPUT: current directory")
        else:
            print("INPUT: specific directory = " + args.i)

        if args.o is None:
            print("OUTPUT: current directory")
        else:
            print("OUTPUT: specific directory = " + args.o)

        if args.txt is not None:
            print(".txt output")

        if args.rtf is not None:
            print(".rtf output")

        print("[End of Main]")


if __name__ == '__main__':
    MainClass.main()

Output

C:\Users\pc\source>python argparse_test.py --txt
[Start of Main]
usage: argparse_test.py [-h] [-i I] [-o O] [--txt TXT | --rtf RTF]
argparse_test.py: error: argument --txt: expected one argument

C:\Users\pc\source>

In this source code --txt and --rtf are not expected to receive any argument, and they should also be mutually exclusive.

So, how can I fix this?

Edit (1):

my_group = my_parser.add_mutually_exclusive_group()
my_group.add_argument("--txt", help="output as .txt files", action='store_true')
my_group.add_argument("--rtf", help="output as .rtf files", action='store_true')

The above modification is making the program display both txt and rtf.

C:\Users\pc\source>python argparse_test.py --txt
[Start of Main]
INPUT: current directory
OUTPUT: current directory
.txt output
.rtf output
[End of Main]

C:\Users\pc\source>

Edit (2): testing True/False gives better result:

    if args.txt is True:
        print(".txt output")

    if args.rtf is True:
        print(".rtf output")

Output:

C:\Users\pc\source>python argparse_test.py --txt
[Start of Main]
Namespace(i=None, o=None, rtf=False, txt=True)
INPUT: current directory
OUTPUT: current directory
.txt output
[End of Main]

However, inputting --txt and --rtf at the same time gives an error:

C:\Users\pc\source>python argparse_test.py --txt --rtf
[Start of Main]
usage: argparse_test.py [-h] [-i I] [-o O] [--txt | --rtf]
argparse_test.py: error: argument --rtf: not allowed with argument --txt
user366312
  • 16,949
  • 65
  • 235
  • 452
  • 1
    But they ***are expected*** to receive an argument because you didn't say otherwise. Did you mean to add `action='store_true'`? – Tomerikoo Apr 20 '21 at 18:29
  • '--txt' is a default optional argument. It expects an argument. The problem isn't with the mutually_exclusive. Look at the `usage` `[--txt TXT`. – hpaulj Apr 20 '21 at 18:29
  • Should I apply `action='store_true'` to both of the items? Applying both makes both of them appear on the screen. – user366312 Apr 20 '21 at 18:34
  • What do you mean *"both of them appear in the screen"*? According to your described use-case - yes, you should put both. This makes them `False` by default and then as they are mutually exclusive, only one will always be `True` – Tomerikoo Apr 20 '21 at 18:36
  • @Tomerikoo, see the edit. – user366312 Apr 20 '21 at 18:38
  • What value(s) do you expect for this two arguments? You are in control. With `store_true` the value will be either `True/False`. With the default `store`, the value will either be the default `None`, or the string the user supplies. Add a `print(args)` before doing the `args` testing to make debugging easier. – hpaulj Apr 20 '21 at 18:40
  • Ah I see. Because you are checking `if args.rtf is not None`. It will never be `None`. It will either be `True` or `False`. You should probably just change to `if args.rtf:`... – Tomerikoo Apr 20 '21 at 18:41
  • @Tomerikoo, ok. thanks. got it. – user366312 Apr 20 '21 at 18:44
  • I have edited the title to better reflect the real problem here (and the linked solution) to make it a better sign-post now that it's a duplicate – Tomerikoo Apr 20 '21 at 18:48
  • @Tomerikoo, True/False testing is working. But, the problem remains with inputting both -`-txt` and `--rtf` at the same time. If both are inputted, the program should take the 1st one, not generate an error. – user366312 Apr 20 '21 at 18:59
  • No it shouldn't. That's not what mutually exclusive mean... It means that they ***can't*** come together, i.e. raise an error... I am not aware of a way to check the position of passed arguments, but anyway, if that's what you're after - you'll have to do it manually – Tomerikoo Apr 20 '21 at 19:01
  • @Tomerikoo, check the edit(2). – user366312 Apr 20 '21 at 19:03
  • Yes, I saw. As I said - `argument --rtf: not allowed with argument --txt` - that's what mutually exclusive means... The code works as intended. If you wanted to do something else, you might need to do it manually, or use a different method. That might be a separate question. Feel free to tag me if you post such question (with clear details of what exactly you're trying to do) - I will be glad to help there – Tomerikoo Apr 20 '21 at 19:05
  • @Tomerikoo, thanks. Got it. :) – user366312 Apr 20 '21 at 19:12

0 Answers0