argparse change definition of argument

落爺英雄遲暮 提交于 2019-12-08 00:33:01

问题


I set up my argument parser as follows:

parser=argparse.ArgumentParser()
parser.add_argument('--point',help='enter a point (e.g. 2,3,4)')
parser.parse_args('--point=-2,5,6'.split())  #works
parser.parse_args('--point -2,5,6'.split())  #doesn't work :(

Is there any way to tell argparse that strings which match the regular expression r"-\d+.*" are not options but an argument of an option?

Also note that I could do something like this:

parser.add_argument('--point',nargs='*')
parser.parse_args('--point -2 5 6'.split())

but that's not really how I want it to work.


回答1:


I think preprocessing sys.argv is the most straightforward way here. Consider for example:

import argparse, re

parser=argparse.ArgumentParser()
parser.add_argument('--point',help='enter a point (e.g. 2,3,4)')

args = '--point -2,5,6'.split() # or sys.argv

is_list = re.compile(r'^-?[\d,.]+$')
args = ['"%s"' % x if is_list.match(x) else x for x in args]
print parser.parse_args(args)

This returns Namespace(point='"-2,5,6"') which should be easy to parse.




回答2:


You could change the prefix char so - is no longer recognized as indicating the start of an argument. It does look a bit weird but it is useful when negative numbers may appear in the arguments.

import argparse
parser=argparse.ArgumentParser(prefix_chars = '@')
parser.add_argument('@@point',help='enter a point (e.g. 2,3,4)')
args = parser.parse_args('@@point=-2,5,6'.split())  #works
print(args)
# Namespace(point='-2,5,6')

args = parser.parse_args('@@point -2,5,6'.split())  #work also
print(args)
# Namespace(point='-2,5,6')



回答3:


If you don't mind messing around with argparse internals, argparse already does something very similar to what I want to do. One of the classes that ArgumentParser inherits from has this line in __init__

import re as _re
...
self._negative_number_matcher = _re.compile(r'^-\d+$|^-\d*\.\d+$')

So to get my example to work, we just need to swap out an appropriate regex...

parser._negative_number_matcher = re.compile(r'^-\d+|^-\d*\.\d+')

Usually I'm not very much in favor of messing around with the internals of a class when they're prefixed by an underscore (as it is implementation dependent and liable to change) -- However, in this case, I think it's probably ok because:

  • If argparse changes that variable name, it doesn't hurt, we're just back to the case where "--print -2,3,4" doesn't work again.
  • I can't think of any better way to determine if something is a number than regex (I suppose they could try to cast to a float and catch the exception, but if they did that, they wouldn't have a variable named _negative_number_matcher anymore and again, argparse would still work fine except in this corner case where it doesn't do what I want)


来源:https://stackoverflow.com/questions/11023673/argparse-change-definition-of-argument

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!