2012-06-13 6 views
2

Я настроил свой аргумент анализатор следующим образом:argparse определения изменения аргумента

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 :(

Есть ли способ сказать argparse, что строки, которые соответствуют регулярному выражению r"-\d+.*" не являются опционами, но аргумент опции?

Также обратите внимание, что я мог сделать что-то вроде этого:

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

, но это не совсем, как я хочу работать.

+0

Я бы предложил принудительно включить аргументы точки привязки в скобках (или что-то вроде логического) ... – jadkik94

+0

@ jadkik94 - самые логичные фигурные скобки (для меня) - это скобки - но они имеют особое значение в оболочке и будут иметь чтобы ускользнуть ... Плюс это делает код немного более уродливым при расщеплении ... – mgilson

ответ

1

Если вы не против возиться с внутренними элементами argparse, argparse уже делает что-то очень похожее на то, что я хочу делать. Один из классов, которые ArgumentParser наследуют от этой линии имеют в __init__

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

Таким образом, чтобы мой пример работать, нам просто нужно поменять соответствующее регулярное выражение ...

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

Обычно я m не очень в пользу возиться с внутренними классами, когда они имеют префикс подчеркивания (поскольку он зависит от реализации и может измениться). Однако в этом случае я думаю, что это, вероятно, нормально, потому что:

  • Если argparse изменяет это имя переменной, это не повредит, мы вернемся к случаю, когда «-print -2,3,4» не работает снова.
  • Я не могу придумать лучшего способа определить, является ли что-то числом, чем регулярным выражением (я полагаю, они могут попытаться применить к float и поймать исключение, но если они это сделают, у них не будет переменной названный _negative_number_matcher больше, и снова, argparse бы еще работать нормально, за исключением в этом угловом случае, если он не делает то, что я хочу)
+0

Если вы наткнетесь на это с помощью поиска в Google - посмотрите на другие ответы. Они, вероятно, лучше, чем этот ответ, но это делает то, что я хотел. – mgilson

1

Вы можете изменить prefix char так, чтобы - больше не был признан как указывающий начало аргумента. Это выглядит немного странно, но полезно, когда отрицательные числа могут появляться в аргументах.

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') 
+0

Я не думал об этом (возможно, должен был бы), - но в моем парсере гораздо больше аргументов, и это выглядит немного глупо чтобы превзойти ожидаемое использование только для этого углового случая ... Я люблю argparse, но иногда мне хотелось бы, чтобы он оставил немного больше внутренних открытий, чтобы я мог выполнить что-то подобное с помощью подкласса. (Я полагаю, я мог бы preprocess sys.argv присоединиться к аргументам, подобным этому с помощью = ...) – mgilson

2

Я думаю, что предварительная обработка sys.argv это самый простой способ здесь. Рассмотрим, например:

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) 

Это возвращает Namespace(point='"-2,5,6"'), который должен быть легко разобрать.

Смежные вопросы