0

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.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • What shell are you using? – slothrop Aug 22 '23 at 17:02
  • Possibly related: https://stackoverflow.com/questions/19120247/python-sys-argv-to-preserve-or – slothrop Aug 22 '23 at 17:04
  • `Namespace(a=0, b=False, s=['-b'])` ?? did you mean `c` and not `s` ? – D.L Aug 22 '23 at 17:06
  • The first parse_args` should return `Namespace(a=None, b=False, c='-a 1')`. Use ' -b' (with leading space) if you don't want it to be a '0b' flag string. `argparse` strongly prefers to treat a dashed string as an `optionals` flag. – hpaulj Aug 22 '23 at 19:52
  • On further thought, that '-a 1' might be treated as a '-a' flag. I'd have to test it. In any case, arguments starting with a dash can a be problem for argparse. Try to avoid them. – hpaulj Aug 22 '23 at 19:55

0 Answers0