我來試試你的最新的自定義操作:
In [34]: parser=argparse.ArgumentParser()
In [35]: parser.add_argument('--env')
In [36]: parser.add_argument('--props',nargs='*',action=NameValueAction)
Out[36]: NameValueAction(option_strings=['--props'], dest='props', nargs='*', const=None, default=None, type=None, choices=None, help=None, metavar=None)
我得到一個unrecognized arguments
誤差parse_args
。你的動作正確定義爲未知:
In [37]: args=parser.parse_args('--env=target_env --props name1=value1 name2=value2 module/'.split())
usage: ipython2.7 [-h] [--env ENV] [--props [PROPS [PROPS ...]]]
ipython2.7: error: unrecognized arguments: module/
...
隨着parse_known_args我可以看到指定參數和演員沒有錯誤消息:
In [38]: parser.parse_known_args('--env=target_env --props name1=value1 name2=value2 module/'.split())
Out[38]:
(Namespace(env='target_env', name1='value1', name2='value2', props=None),
['module/'])
因此,所有的字符串後--props
被傳遞作爲values
該行動。它將值分配給名稱空間並返回。 parse_known_args
將unrecognized
值從名稱空間中取出並放入該extras
列表中。現在
我將添加一個位置,希望它會採取module/
字符串:
In [39]: parser.add_argument('foo')
In [40]: parser.parse_known_args('--env=target_env --props name1=value1 name2=value2 module/'.split())
usage: ipython2.7 [-h] [--env ENV] [--props [PROPS [PROPS ...]]] foo
ipython2.7: error: too few arguments
...
哎呀,不同的錯誤,甚至parse_known_args
。問題在於'module /'仍然在給--props
,給foo
留下任何東西。 --props
有一個*
nargs,這意味着它會獲得所有符合條件的參數(沒有-
)。將'module /'放在命名空間unknown
沒有幫助。解析器不會重新評估此列表中的字符串。
我可以使用' - '來表示後面的所有字符串都是定位符。現在--props
沒有收到或處理'模塊'。相反,在下一次處理定位點時,它會被foo
消耗。
In [41]: parser.parse_known_args('--env=target_env --props name1=value1 name2=value2 -- module/'.split())
Out[41]:
(Namespace(env='target_env', foo='module/', name1='value1', name2='value2', props=None),
[])
另一種任選的,如可用於標記的「--props」參數的結尾「--env」:
In [42]: parser.parse_known_args('--props name1=value1 name2=value2 --env=target_env module/'.split())
Out[42]:
(Namespace(env='target_env', foo='module/', name1='value1', name2='value2', props=None),
[])
注意progs=None
出現在命名空間。這是因爲解析器在解析開始時將所有Action默認值加載到名稱空間中。你可以使用default=argparse.SUPPRESS
來防止這種情況。
解釋見的參數如何分配到「*」可選這個錯誤/問題,什麼可以做,以保留一些用於以下positionals:
http://bugs.python.org/issue9338 argparse optionals with nargs='?', '*' or '+' can't be followed by positionals
https://stackoverflow.com/a/33405960/901925是另一個最近的SO問題,涉及到一個常規的位置,後面跟着兩個'?' positionals。
正如我在評論中指出的,與optparse
不同。我相信在optparse
每個動作(或等效)消耗盡可能多的字符串,並留下其餘的行動。在中,單個操作無權訪問主列表(arg_strings
)。這是解析器決定Action獲取的字符串數量。
從argparse.py
文件更多細節。這是對parse_args相關部分的總結。
_parse_known_args(self, arg_strings, namespace):
# arg_strings - master list of strings from sys.argv
start_index = 0
while start_index<amax:
# step through arg_strings processing postionals and optionals
consume_positionals()
start_index = next_option_string_index
start_index = consume_optional(start_index)
consume_optional(start_index): # function local to _parse_known_args
...
start = start_index + 1
arg_count = <fn of available arguments and nargs>
stop = start + arg_count
args = arg_strings[start:stop]
<action = CustomAction.__call__>
take_action(action, args, option_string)
return stop
take_action(action, argument_strings, ...): # another local function
# argument_strings is a slice of arg_strings
argument_values = self._get_values(action, argument_strings)
# _get_values passes strings through the action.type function
action(self, namespace, argument_values, option_string)
# no return
的淨效應是,你CustomAction.__call__
會從主arg_strings
列表的片段中所取得的values
列表。它無法訪問arg_strings
,也無法訪問該片的start
和stop
。所以它不能改變字符串本身或任何後續動作的分配。
另一個想法是,讓你無法解析成self.dest
值。
class NameValueAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
extras = []
for value in values:
try:
n, v = value.split('=')
setattr(namespace, n, v)
except ValueError:
extras.append(value)
if len(extras):
setattr(namespace, self.dest, extras)
然後解析(不foo
位置)會產生:
In [56]: parser.parse_args('--props name1=value1 p1 name2=value2 module/'.split())
Out[56]: Namespace(env=None, name1='value1', name2='value2', props=['p1', 'module/'])
args.props
現在包含['p1','module/']
,字符串--props
了,但無法解析爲n=v
對。這些可以根據需要進行解析後重新定位。
解析器根據其「nargs」和任何後續動作的「nargs」分配動作獲取的「values」列表。與'optparse'相比,這一行爲不會剝離某些主列表中的值。圍繞不同的positionals,optionals和'nargs'混合來查看每個值有多少個值。 – hpaulj
另請參閱http://stackoverflow.com/questions/33301000/custom-parsing-function-for-any-number-of-arguments-in-python-argparse。它從多個'--flag = key:value'字符串構建一個字典。 – hpaulj