I define an argument parser in a Python script (script.py
) as follows:
import arparse
import sys
# define the parser
parser = argparse.ArgumentParser()
parser.add_argument("-a", type=int)
parser.add_argument("-b", action="store_true")
parser.add_argument("-c", type=str)
# and parse the arguments from sys.argv or a list
parser.parse(sys.argv[1:])
If I call my program like this (call 1):
python script.py -c "-a 1"
sys.argv[1:]
looks like ["-c", "-a 1"]
. That's what I expected so far. Here, I want the resulting namespace to be:
Namespace(a=0, b=False, s=['-a 1'])
But argparse
reads the second list element not as argument of -c
but as individual argument and raises an error, because -s
expects one argument. I had a deep look into argparse, because so far I thought this is a bug in argparse. So, I locally "fixed" argparse to detect "-a 1"
as argument of -c
and not as -a
argument. (Basically, I told argparse that there's a difference between "-a 1"
and "-a=1"
.)
But then I realized, that this does not help when calling my script by (call 2):
python script.py -c "-b"
as my trick doesn't work any more (there's no potential =
to not be detected). Here my expectation is to get:
Namespace(a=0, b=False, s=['-b'])
but argparse again reads the "-b"
as new argument and complains that -s
got no argument. And here I cannot trick argparse because it needs to be able to distinguish between call 2 and this (call 3):
python script.py -c "-b"
But for both calls 2 and 3, sys.argv[1:]
looks like ["-c", "-b"]
.
Then, I thought it might be a bug in the sys
library and the calls 2 and 3 should end up in two different arrays, i.e. ["-c", "\"-b\""]
and ["-c", "-b"]
but this might break many other applications that rely on the current implementation of sys
.
For my specific case, I found a hack to make argparse parse my stuff the way I want it to get parsed by modifying sys.argv[1:]
before passing it to the parser. But in general, I don't know how to solve the problem/inconsistency or if one just has to accept it.