Question: My script takes -d, --delimiter as argument: parser.add_argument('-d', '--delimiter')  but when I pass it -- as delimiter, it is empty script.py --delimiter='--'  I know -- is special in argument/parameter parsing, but I am using it in the form --option='--' and quoted. Why does it not work? I am using Python 3.7.3 Here is test code: #!/bin/python3 import argparse parser = argparse.ArgumentParser() parser.add_argument('--delimiter') parser.add_argument('pattern') args = parser.parse_args() print(args.delimiter)  When I run it as script --delimiter=-- AAA it prints empty args.delimiter.

Answer: This looks like a bug. You should report it. This code in argparse.py is the start of _get_values, one of the primary helper functions for parsing values: if action.nargs not in [PARSER, REMAINDER]: try: arg_strings.remove('--') except ValueError: pass  The code receives the -- argument as the single element of a list ['--']. It tries to remove '--' from the list, because when using -- as an end-of-options marker, the '--' string will end up in arg_strings for one of the _get_values calls. However, when '--' is the actual argument value, the code still removes it anyway, so arg_strings ends up being an empty list instead of a single-element list. The code then goes through an else-if chain for handling different kinds of argument (branch bodies omitted to save space here): # optional argument produces a default when not present if not arg_strings and action.nargs == OPTIONAL: ... # when nargs='*' on a positional, if there were no command-line # args, use the default if it is anything other than None elif (not arg_strings and action.nargs == ZERO_OR_MORE and not action.option_strings): ... # single argument or optional argument produces a single value elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]: ... # REMAINDER arguments convert all values, checking none elif action.nargs == REMAINDER: ... # PARSER arguments convert all values, but check only the first elif action.nargs == PARSER: ... # SUPPRESS argument does not put anything in the namespace elif action.nargs == SUPPRESS: ... # all other types of nargs produce a list else: ...  This code should go through the 3rd branch, # single argument or optional argument produces a single value elif len(arg_strings) == 1 and action.nargs in [None, OPTIONAL]:  but because the argument is missing from arg_strings, len(arg_strings) is 0. It instead hits the final case, which is supposed to handle a completely different kind of argument. That branch ends up returning an empty list instead of the '--' string that should have been returned, which is why args.delimiter ends up being an empty list instead of a '--' string.  This bug manifests with positional arguments too. For example, import argparse parser = argparse.ArgumentParser() parser.add_argument('a') parser.add_argument('b') args = parser.parse_args(["--", "--", "--"]) print(args)  prints Namespace(a='--', b=[])  because when _get_values handles the b argument, it receives ['--'] as arg_strings and removes the '--'. When handling the a argument, it receives ['--', '--'], representing one end-of-options marker and one actual -- argument value, and it successfully removes the end-of-options marker, but when handling b, it removes the actual argument value.