问题
I am trying to write a Nagios style check to use with Nagios. I have working script that takes in something like -w 15 -c 10
and interprets that as "Warning at 15%, Critical at 10%". But I just realized that in the built-in Nagios plugins, the same arguments would mean "Warning at 15MB, Critical at 10MB"; I would instead need to enter -w 15% -c 10%
to get the above behavior.
So my question is, what is the best way to make my script behave like the built-in Nagios scripts? The only way I can think of is accepting the argument as a string and parsing it, but is there a neater way?
回答1:
You can use your own class as type for the arguments:
import argparse
class Percent(object):
def __new__(self, percent_string):
if not percent_string.endswith('%'):
raise ValueError('Need percent got {}'.format(percent_string))
value = float(percent_string[:-1]) * 0.01
return value
parser = argparse.ArgumentParser(description="with percent")
parser.add_argument('-w', '--warning', type=Percent)
parser.add_argument('-c', '--critcal', type=Percent)
args = parser.parse_args()
print(args.warning)
Output:
python parse_percent.py -w 15%
0.15
python parse_percent.py -w 15
usage: parse-percent.py [-h] [-w WARNING] [-c CRITCAL]
parse-percent.py: error: argument -w/--warning: invalid Percent value: '15'
Version that works with percent or MB
class Percent(object):
def __new__(self, percent_string):
if percent_string.endswith('%'):
return float(percent_string[:-1]), 'percent'
else:
return float(percent_string), 'MB'
parser = argparse.ArgumentParser(description="with percent")
parser.add_argument('-w', '--warning', type=Percent)
parser.add_argument('-c', '--critcal', type=Percent)
args = parser.parse_args()
value, unit = args.warning
print('{} {}'.format(value, unit))
Output:
python parse_percent.py -w 15
15.0 MB
python parse_percent.py -w 15%
15.0 percent
回答2:
This is the type
function which I believe behaves the same as @Mike's
class:
def percent(astr):
if astr.endswith('%'):
return float(astr[:-1]), 'percent'
else:
return float(astr), 'MB'
parser = argparse.ArgumentParser(description="with percent")
parser.add_argument('-w', '--warning', type=Percent)
parser.add_argument('-c', '--critcal', type=percent)
args = parser.parse_args()
print(args)
testing:
1058:~/mypy$ python3 stack41741065.py
Namespace(critcal=None, warning=None)
1059:~/mypy$ python3 stack41741065.py -w 14 -c 14
Namespace(critcal=(14.0, 'MB'), warning=(14.0, 'MB'))
1059:~/mypy$ python3 stack41741065.py -w 14% -c 14%
Namespace(critcal=(14.0, 'percent'), warning=(14.0, 'percent'))
1059:~/mypy$ python3 stack41741065.py -w bad
usage: stack41741065.py [-h] [-w WARNING] [-c CRITCAL]
stack41741065.py: error: argument -w/--warning: invalid Percent value: 'bad'
1100:~/mypy$ python3 stack41741065.py -c bad
usage: stack41741065.py [-h] [-w WARNING] [-c CRITCAL]
stack41741065.py: error: argument -c/--critcal: invalid percent value: 'bad'
type
just has to be a callable that takes a string, and returns a value. Here it is returning a tuple, which the store
Action just puts in the namespace
. If the callable returns a ValueError, TypeError or argparse.ArgumentTypeError
, the error display should be the same. In these examples the initial error is the ValueError produced by float('bad')
. The default error message is uses the callable's name (Percent
v percent
).
An example of post-parsing parsing is:
if args.o is not None:
try:
args.o = percent(args.o)
except ValueError:
parser.error('invalid args.o value')
print(args)
100:~/mypy$ python3 stack41741065.py
Namespace(critcal=None, o=None, warning=None)
Namespace(critcal=None, o=None, warning=None)
1107:~/mypy$ python3 stack41741065.py -o 14
Namespace(critcal=None, o='14', warning=None)
Namespace(critcal=None, o=(14.0, 'MB'), warning=None)
1107:~/mypy$ python3 stack41741065.py -o 14%
Namespace(critcal=None, o='14%', warning=None)
Namespace(critcal=None, o=(14.0, 'percent'), warning=None)
1107:~/mypy$ python3 stack41741065.py -o bad
Namespace(critcal=None, o='bad', warning=None)
usage: stack41741065.py [-h] [-w WARNING] [-c CRITCAL] [-o O]
stack41741065.py: error: invalid args.o value
argparse.FileType
is an example of a type
function factory class.
来源:https://stackoverflow.com/questions/41741065/best-way-to-make-argument-parser-accept-absolute-number-and-percentage