How to make argparse accept "-4^2+5.3*abs(-2-1)/2" string argument?

Jach Feng jfong at ms4.hinet.net
Sat Jan 28 21:55:34 EST 2023


Mark Bourne 在 2023年1月28日 星期六晚上10:00:01 [UTC+8] 的信中寫道:
> Jach Feng wrote: 
> > Jach Feng 在 2023年1月22日 星期日上午11:11:22 [UTC+8] 的信中寫道: 
> >> Fail on command line, 
> >> 
> >> e:\Works\Python>py infix2postfix.py "-4^2+5.3*abs(-2-1)/2" 
> >> usage: infix2postfix.py [-h] [infix] 
> >> infix2postfix.py: error: unrecognized arguments: -4^2+5.3*abs(-2-1)/2 
> >> 
> >> Also fail in REPL, 
> >> 
> >> e:\Works\Python>py 
> >> Python 3.8.8 (tags/v3.8.8:024d805, Feb 19 2021, 13:08:11) [MSC v.1928 32 bit (Intel)] on win32 
> >> Type "help", "copyright", "credits" or "license" for more information. 
> >>>>> import argparse 
> >>>>> parser = argparse.ArgumentParser(description='Convert infix notation to postfix') 
> >>>>> parser.parse_args("-4^2+5.3*abs(-2-1)/2") 
> >> usage: [-h] 
> >> : error: unrecognized arguments: - 4 ^ 2 + 5 . 3 * a b s ( - 2 - 1 ) / 2 
> >> 
> >> Just can't figure out where is wrong!? 
> >> 
> >> --Jach 
> > I have to admit that I don't know the background upon which the argparse was built. The good side is that I don't carry its historical knowledge ( or burden?), that's why I can use it in a new way which may make someone feel uneasy.
> If you can use it in the way you want, that's great. I thought you were 
> asking here because you *couldn't* use it the way you want. 
> 
> You're writing a command-line application. Your users are either 
> already familiar with the conventions of command-line applications, or 
> they'll soon need to be. 
> 
> If your application supports options beginning with a "-" (which is what 
> argparse gives you, even if only the default "-h" and "--help" options 
> are actually valid), and you also need to be able to pass positional 
> arguments which begin with a "-", you need some way for the user to 
> indicate whether any particular argument is an option or positional. 
> Using "--" to indicate that all subsequent arguments are positional, not 
> options, is a common convention. 
> 
> Some of your users might already be familiar with that convention from 
> other command-line tools. By using the same convention, you'd be making 
> it easier for them to use yours. Others might not already be familiar 
> with the convention, but by being consistent with other tools you'd 
> still be helping them when they eventually do come across it elsewhere. 
> You can always include an explanation of using "--" in your usage output 
> or other documentation. 
> 
> Apart from dealing with how to pass an argument beginning with "-", your 
> users will also likely have to deal with the features of whichever shell 
> they're using, which you have no control over. For example, it's quite 
> common to need to enclose an argument in quotes if it contains spaces. 
> It may also be necessary to use quotes if certain special characters are 
> used, such as "*", "?" or "$" (perhaps "%" on Windows).
> > The reason I am still keep on using argparse on this "one positional argument only" CLI app is that I can't see what advantage I can get when writing code to handling sys.argv directly for the following two situations, 
> > ----- 
> > e:\Works\Python>py infix2postfix.py 
> > usage: infix2postfix.py [-h] infix 
> > infix2postfix.py: error: the following arguments are required: infix 
> > 
> > e:\Works\Python>py infix2postfix.py -h 
> > usage: infix2postfix.py [-h] infix 
> > 
> > Convert infix notation to postfix 
> > 
> > positional arguments: 
> > infix Put equations in quote if there is space in it and separate each one with a comma, ie. 
> > "-4^2+5.3*abs(-2-1)/2, abs(Abc)*(B+C)/D, (-3) * sqrt(1-(x1/7)*(y1/7)) * sqrt(abs((x0-4.5)/(y0-4)))" 
> > 
> > optional arguments: 
> > -h, --help show this help message and exit 
> > ----- 
> > 
> > comparing with code using the argparse below, 
> > 
> > import argparse 
> > sample = "-4^2+5.3*abs(-2-1)/2, abs(Abc)*(B+C)/D, (-3) * sqrt(1-(x1/7)*(y1/7)) * sqrt(abs((x0-4.5)/(y0-4)))" 
> > parser = argparse.ArgumentParser(description='Convert infix notation to postfix') 
> > parser.add_argument('infix', 
> > help='Put equations in quote if there is space in it and separate each one with a comma, ie. "{}"'.format(sample)) 
> > 
> > import sys 
> > if len(sys.argv) > 1 and not '-h' in sys.argv: 
> > ....sys.argv.insert(1, '--') 
> > args = parser.parse_args()
> Personally, I do quite often use argparse even for simple cases, partly 
> because it produces nice usage details, and deals with wrapping the 
> output to whatever width the console is. But I work with it rather than 
> against it, and accept that a "--" is needed if a positional argument 
> starts with a "-". 
> 
> I notice you explain the need to enclose the equation in quotes if it 
> contains spaces. That's not even a feature of your application, but of 
> the shell used to call it. So why so much objection to explaining the 
> need for "--"? 
> 
> Depending on the shell, there are other cases where quoting might be 
> needed, e.g. if the equation includes a "*" or "?" and happens to look 
> like a pattern matching files in the current directory (most shells I've 
> used pass the pattern unchanged if it doesn't match any files). In 
> bash, if a "$" is used I'd need to enclose that in 'single quotes' 
> (can't even use "double quotes" for that one). You can't really expect 
> to document all that sort of thing, because it depends on which shell 
> the user happens to run your application from - you just have to trust 
> the user to know or learn how to use their shell. 
> 
> -- 
> Mark.
Thank you for detail explanation of the role the shell is involved in this problem. I'm very appreciated!

It seems that a CLI app may become very complex when dealing with different kind of shell, and may not be possible to solve its problem. But the good thing in my app is that I need only to handle math equation:-)

> So why so much objection to explaining the need for "--"?
Because of using " to enclose a space separated string is a common convention, and adding a "--" is not:-)

--Jach


More information about the Python-list mailing list