Reputation: 51023
When using argparse I get this weird ValueError for help option. All other options work fine. Only the help option is not working, which is weird.
Here is the error message:
chaudhary@localhost:~/code/python/logmein$ ./logmein.py --bla
Usage: ./logmein.py [filename <Default: .login.txt>] || [password] || [username password]
chaudhary@localhost:~/code/python/logmein$ ./logmein.py --boo
Usage: ./logmein.py [filename <Default: .login.txt>] || [password] || [username password]
chaudhary@localhost:~/code/python/logmein$ ./logmein.py -b
Usage: ./logmein.py [filename <Default: .login.txt>] || [password] || [username password]
chaudhary@localhost:~/code/python/logmein$ ./logmein.py -h
Unexpected Error: <class 'ValueError'>
Details: unsupported format character 'p' (0x70) at index 1
Traceback (most recent call last):
File "./logmein.py", line 222, in <module>
main(sys.argv)
File "./logmein.py", line 158, in main
args, otherthings = parser.parse_known_args()
File "/usr/lib64/python3.3/argparse.py", line 1737, in parse_known_args
namespace, args = self._parse_known_args(args, namespace)
File "/usr/lib64/python3.3/argparse.py", line 1943, in _parse_known_args
start_index = consume_optional(start_index)
File "/usr/lib64/python3.3/argparse.py", line 1883, in consume_optional
take_action(action, args, option_string)
File "/usr/lib64/python3.3/argparse.py", line 1811, in take_action
action(self, namespace, argument_values, option_string)
File "/usr/lib64/python3.3/argparse.py", line 1015, in __call__
parser.print_help()
File "/usr/lib64/python3.3/argparse.py", line 2339, in print_help
self._print_message(self.format_help(), file)
File "/usr/lib64/python3.3/argparse.py", line 2323, in format_help
return formatter.format_help()
File "/usr/lib64/python3.3/argparse.py", line 276, in format_help
help = self._root_section.format_help()
File "/usr/lib64/python3.3/argparse.py", line 206, in format_help
func(*args)
File "/usr/lib64/python3.3/argparse.py", line 293, in _format_usage
usage = usage % dict(prog=self._prog)
ValueError: unsupported format character 'p' (0x70) at index 1
Here is my code
# Parse command line arguments
from argparse import ArgumentParser
usage = "%prog [-f credential_file]"
parser = ArgumentParser(usage=usage)
parser.add_argument("-f", "--file", type=str, dest="file",
help="Use the specified file")
parser.add_argument("-o", "--logout", action='store_true', dest="logout",
help="Logout")
#parser.add_argument('otherthings', nargs='*')
#args = parser.parse_args()
args, otherthings = parser.parse_known_args()
argc = len(otherthings)
if args.file != None:
username, password = parse_file_for_credential(args.file)
Now I can't find out why this ValueError comes and that too only for --help option.
Upvotes: 1
Views: 1938
Reputation: 159915
The issue is that when argparse attempts to interpolate your usage
string Python sees the following character sequence: %p
. Since p
is not a valid conversion flag, Python raises the ValueError
.
You can generate this error yourself at the REPL:
>>> "This is valid: %s" % "magic"
"This is valid: magic"
>>> "This will raise a ValueError: %p" % "magic"
ValueError: unsupported format character 'p' (0x70)
The reason this is happening is because you use %prog
rather than the correct %(prog)s
(note the parenthesis around the key in %s
). Change usage = "%prog [-f credential_file]"
to usage = "%(prog)s [-f credential_file]"
as Rob suggests and everything will work.
argparse provides metadata like the program's name via named format arguments to allow the arguments to appear in any order, and to allow for repetition. Positional arguments cannot be re-used and must appear in the same order as they are provided:
>>> "If I want another %s then I need to add another %s" % ("param", "placeholder")
"If I want another param then I need to add another placeholder"
# There is no way to change the order around to be
# "If I want another placeholder then I need to add another param"
# without changing the order of the parameters passed to `%`
while named arguments can be repeated and used in any order:
>>> s = "Any order, %(two)s / %(one)s. Repeats %(one)s / %(two)s are possible"
>>> s % {"one": "first", "two": "last"}
"Any order, last / first. Repeats first / last are possible"
Upvotes: 3
Reputation: 168626
Quoting the documentation:
Note that the program name, whether determined from
sys.argv[0]
or from theprog=
argument, is available to help messages using the%(prog)s
format specifier.
Try usage = "%(prog)s [-f credential_file]"
Upvotes: 3