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

avi.e.gross at gmail.com avi.e.gross at gmail.com
Sat Jan 28 23:15:22 EST 2023


Jack,

I get uneasy when someone thinks a jackhammer is a handy dandy tool for pushing in a thumbtack that is sitting on my expensive table.

I agree it is quite easy to grab some code that does lot of things and also does something truly minor, and use it for that purpose. Sometimes the cost is that it is far slower. I mean if I want to print the smaller of variables alpha and beta containing integers, I could combine them in something like a list or array and call a nifty sort() function someone wrote that takes a function argument that lets you compare whatever is needed and it likely will work. You get back the result and print the first item in the sorted output or maybe the last. You could have used a simpler function like min(alpha, beta) and skipped making a list of them. Heck, you could have used a fairly simple if statement. 

But if you searched the internet and found a function that takes any number of data items and performs many statistical tests on it tat start with things like mean, median and mode and continues to calculate standard deviation, and skew and standard error and also the min/max/range. Sounds good. It returns some structure/object and you dig into it and find the minimum and you are done!

It sounds like the jackhammer approach to me.

In your case, there is indeed nothing wrong with using the function to help parse the command line arguments and you are being told that it generally works EXCEPT when it is documented NOT TO WORK. It was designed to deal with UNIX conventions so you could call a program with a mix of optional flags and then optional arguments such as filenames or anything else or ALMOST anything else. The early design allowed something like to list files using:

ls - la *.c

or

ls - l -a *.c

Or many more variations that can include newer ways that use longer options. People ran into the problem of having some options that included a word following them that is to be parsed as part of that option and other enhancements. The minus sign or hyphen was chosen and is not trivial to change. So the idea was to add a flag with two minus signs that has no meaning other than to say that anything after that is to be somewhat ignored as not being a flag. Thus it is safe for any further arguments to start with a minus sign. 

How does that line up with some of the advice you got?

One idea was to have your users told they should add a " -- " (without quotes) before the formula you want to evaluate. Another was asking if you had a more complex command line with many options that needed a swiss army knife approach. If not, since you have formulas starting with a minus sign that may be used, consider NOT using a tool you admit you did not understand.

And since python like many languages provides you with a data structure that already holds the info you need, use the thumbtack approach or find or write a different library function that extracts what you need in an environment where it is NOT looking for things with a minus sign.

You know when you go to a doctor and ask why a part of your skin  is bleeding and so on, and you admit you keep scratching yourself, rather than suggesting complex surgeries or putting your hands in a cast to keep you from scratching, they may first try telling you to NOT DO THAT and let it heal.

Do note a final point. There is nothing magical about using a minus sign in UNIX and they could have insisted say that command line arguments be placed in square brackets or some other method to identify them. It seemed harmless to use a minus sign at the time. But the programs they includes starting using so many allowed tweaks of many kinds, that it got really hard to parse what was being asked and thus several libraries of functions have been built that manage all that. Your problem is far from unique as any program trying to deal with an argument for a filename that begins with a minus sign will have a similar problem. Programs like grep often take an argument that is a regular expression or other utilities take a "program" that also may for whatever reason start with a minus sign. 

Some people ask a question and you have asked many here, and got answers. Usually you accept what people tell you better. I am trying to say that the issue is not whether you are using the wrong tool in general. It is that NOW that you know there is sometimes a problem, you resist understanding it was never designed to do what you want.


-----Original Message-----
From: Python-list <python-list-bounces+avi.e.gross=gmail.com at python.org> On Behalf Of Jach Feng
Sent: Saturday, January 28, 2023 12:04 AM
To: python-list at python.org
Subject: Re: How to make argparse accept "-4^2+5.3*abs(-2-1)/2" string argument?

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.

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()
--
https://mail.python.org/mailman/listinfo/python-list



More information about the Python-list mailing list