'python: argparse throwing value error when combining positional and optional argument

I'm trying to use the argparse library in python to read in optional and required arguments. So far I'm doing this:

import argparse
parser = argparse.ArgumentParser(description='Cleanup Script for Folder')

parser.add_argument('PATH_TO_WORKDIR_ROOT',
                    type=str,
                    dest='PATH_TO_WORKDIR_ROOT',
                    action='store',
                    help='(absolute or) relative path to directory \n   to work on, e.g. "..\MyFolder\\"')
parser.add_argument('--PATH_TO_BACKUP_ROOT',
                    type=str,
                    dest='PATH_TO_BACKUP_ROOT',
                    action='store',
                    help='(absolute or) relative path to Backup-Directory \n   default is ".\BACKUP\"')

args = parser.parse_args()

Now I'm testing my code and it gives me a value-error that I don't understand:

$ python argparsetest.py --help
Traceback (most recent call last):  
File "argparsetest.py", line 5, in <module>
    parser.add_argument('PATH_TO_WORKDIR_ROOT', type=str, dest='PATH_TO_WORKDIR_ ROOT', action='store', help='(absolute or)
relative path to directory \n   to wo rk on, e.g. "..\MyFolder\\"')  
File "C:\Program
Files\Enthought\Canopy\App\appdata\canopy-1.3.0.1715.win-x86_
64\lib\argparse.py", line 1262, in add_argument
    raise ValueError('dest supplied twice for positional argument') ValueError: dest supplied twice for positional argument

There's only one positional argument, isn't there and the destinations are different. I don't really understand the hassle :)

Thanks a lot in advance!



Solution 1:[1]

Look at the following code in argparse.py:

# =======================
# Adding argument actions
# =======================
def add_argument(self, *args, **kwargs):
    """
    add_argument(dest, ..., name=value, ...)
    add_argument(option_string, option_string, ..., name=value, ...)
    """

    # if no positional args are supplied or only one is supplied and
    # it doesn't look like an option string, parse a positional
    # argument
    chars = self.prefix_chars
    if not args or len(args) == 1 and args[0][0] not in chars:
        if args and 'dest' in kwargs:
            raise ValueError('dest supplied twice for positional argument')
        kwargs = self._get_positional_kwargs(*args, **kwargs)

Since you did not precede -- to PATH_TO_WORKDIR_ROOT it thinks that the first argument is dest therefore raising the Error when you supply dest again as a named argument.

Solution 2:[2]

parser.add_argument('PATH_TO_WORKDIR_ROOT',
                type=str,
                action='store',
                help='(absolute or) relative path to directory \n   to work on, e.g. "..\MyFolder\\"')

Remove dest from the first add_argument call

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 MotKohn
Solution 2 Ahmed Yossef