2013-04-01 29 views
155

我試圖將列表作爲參數傳遞給命令行程序。是否有argparse選項作爲選項傳遞列表?作爲選項傳遞列表的argparse選項

parser.add_argument('-l', '--list', 
         type=list, action='store', 
         dest='list', 
         help='<Required> Set flag', 
         required=True) 

腳本被稱爲像下面

python test.py -l "265340 268738 270774 270817" 

回答

317

TL; DR

使用nargs選項或action選項的'append'設置(取決於您希望用戶界面表現)。

NARGS

parser.add_argument('-l','--list', nargs='+', help='<Required> Set flag', required=True) 
# Use like: 
# python arg.py -l 1234 2345 3456 4567 

nargs='+'需要1個或多個參數,nargs='*'取零個或多個。

追加

parser.add_argument('-l','--list', action='append', help='<Required> Set flag', required=True) 
# Use like: 
# python arg.py -l 1234 -l 2345 -l 3456 -l 4567 

隨着append您提供的選項多次以建立名單。

請勿使用type=list !!! - 您可能不想使用type=list和​​。永遠。


讓我們來看看更詳細的一些不同的方式,可能會嘗試這樣做,最終的結果。

import argparse 

parser = argparse.ArgumentParser() 

# By default it will fail with multiple arguments. 
parser.add_argument('--default') 

# Telling the type to be a list will also fail for multiple arguments, 
# but give incorrect results for a single argument. 
parser.add_argument('--list-type', type=list) 

# This will allow you to provide multiple arguments, but you will get 
# a list of lists which is not desired. 
parser.add_argument('--list-type-nargs', type=list, nargs='+') 

# This is the correct way to handle accepting multiple arguments. 
# '+' == 1 or more. 
# '*' == 0 or more. 
# '?' == 0 or 1. 
# An int is an explicit number of arguments to accept. 
parser.add_argument('--nargs', nargs='+') 

# To make the input integers 
parser.add_argument('--nargs-int-type', nargs='+', type=int) 

# An alternate way to accept multiple inputs, but you must 
# provide the flag once per input. Of course, you can use 
# type=int here if you want. 
parser.add_argument('--append-action', action='append') 

# To show the results of the given option to screen. 
for _, value in parser.parse_args()._get_kwargs(): 
    if value is not None: 
     print(value) 

下面是輸出,你可以期望:

$ python arg.py --default 1234 2345 3456 4567 
... 
arg.py: error: unrecognized arguments: 2345 3456 4567 

$ python arg.py --list-type 1234 2345 3456 4567 
... 
arg.py: error: unrecognized arguments: 2345 3456 4567 

$ # Quotes won't help here... 
$ python arg.py --list-type "1234 2345 3456 4567" 
['1', '2', '3', '4', ' ', '2', '3', '4', '5', ' ', '3', '4', '5', '6', ' ', '4', '5', '6', '7'] 

$ python arg.py --list-type-nargs 1234 2345 3456 4567 
[['1', '2', '3', '4'], ['2', '3', '4', '5'], ['3', '4', '5', '6'], ['4', '5', '6', '7']] 

$ python arg.py --nargs 1234 2345 3456 4567 
['1234', '2345', '3456', '4567'] 

$ python arg.py --nargs-int-type 1234 2345 3456 4567 
[1234, 2345, 3456, 4567] 

$ # Negative numbers are handled perfectly fine out of the box. 
$ python arg.py --nargs-int-type -1234 2345 -3456 4567 
[-1234, 2345, -3456, 4567] 

$ python arg.py --append-action 1234 --append-action 2345 --append-action 3456 --append-action 4567 
['1234', '2345', '3456', '4567'] 

外賣

  • 使用nargsaction='append'
    • nargs可以更簡單˚F從用戶的角度來看,但它可能是不直觀的,如果有位置參數,因爲​​不能說出什麼應該是一個位置參數和屬於nargs;如果您有位置參數,則action='append'可能最終成爲更好的選擇。
    • 以上僅在給出nargs時才爲真'*','+''?'。如果你提供一個整數(例如4),那麼nargs和位置參數的混合選項就沒有問題,因爲​​會準確知道該選項的期望值。
  • 不要使用命令行報價
  • 不要使用type=list,因爲它會返回列表
    • 出現這種情況的一個列表,因爲引擎蓋下​​使用值type脅迫每個人給出的論點你選擇的type,而不是所有參數的聚合。
    • 可以使用type=int(或其他)來獲得整數的列表(或其他)

:我不一般的意思..我的意思是用引號到通過一個列表​​是不是你想要的。

+2

怎麼樣的字符串列表?這會將多個字符串參數(「wassup」,「something」和「else」)轉換爲如下所示的列表列表:[['w','a','s','s','u' ,'','','','','','','','','','','',' l','s','e']] – rd108

+0

@ rd108不,不。如圖所示,這個'add_argument'方法將所有內容解釋爲字符串,包括數字。您必須添加額外的東西才能獲得這些列表清單。我只是複製並粘貼了我發佈的內容,並沒有得到列表清單。你怎麼調用'add_argument'? – SethMMorton

+1

@ rd108我明白了,我敢打賭你正在使用'type = list'選項。不要使用它。這將字符串轉換爲列表,並因此列出了列表。 – SethMMorton

8

此外,以nargs,您可能需要使用choices如果你知道名單提前:

>>> parser = argparse.ArgumentParser(prog='game.py') 
>>> parser.add_argument('move', choices=['rock', 'paper', 'scissors']) 
>>> parser.parse_args(['rock']) 
Namespace(move='rock') 
>>> parser.parse_args(['fire']) 
usage: game.py [-h] {rock,paper,scissors} 
game.py: error: argument move: invalid choice: 'fire' (choose from 'rock', 
'paper', 'scissors') 
24

我更喜歡傳球,我在後面的腳本解析分隔的字符串。原因是這樣的;該列表可以是任何類型的intstr,有時使用nargs如果存在多個可選參數和位置參數,則會遇到問題。

parser = ArgumentParser() 
parser.add_argument('-l', '--list', help='delimited list input', type=str) 
args = parser.parse_args() 
my_list = [int(item) for item in args.list.split(',')] 

然後,

python test.py -l "265340,268738,270774,270817" [other arguments] 

,或者

python test.py -l 265340,268738,270774,270817 [other arguments] 

將正常工作。分隔符也可以是一個空格,它可以在參數值周圍加上引號,就像問題中的例子一樣。

+22

您可以將'type'參數設置爲'lambda s:[int(time)for s.split(',')]'中的項目而不是後處理'args.list'。 – chepner

+3

@ chepner,是的,你是絕對正確的,它會更pythonic - 只是一個小的錯字:'int(time)'應該是'int(item)'。我的例子是我通常做的簡化版本,在這裏我檢查了許多其他的東西,而不是簡單的處理。但要簡單地回答這個問題,我也找到你的方式更優雅.. – dojuba

0

在argparse的add_argument方法使用NARGS參數

我使用NARGS = '' 作爲add_argument參數。我特別用於NARGS =「」與選項,如果我不傳遞任何顯式參數

包含一個代碼段作爲示例來接默認值:

實施例:temp_args1.py

請注意:下面的示例代碼是用python3編寫的。通過改變print語句格式,可以在python2運行

#!/usr/local/bin/python3.6 

    from argparse import ArgumentParser 

    description = 'testing for passing multiple arguments and to get list of args' 
    parser = ArgumentParser(description=description) 
    parser.add_argument('-i', '--item', action='store', dest='alist', 
         type=str, nargs='*', default=['item1', 'item2', 'item3'], 
         help="Examples: -i item1 item2, -i item3") 
    opts = parser.parse_args() 

    print("List of items: {}".format(opts.alist)) 

注:我收集的是被存儲在列表中的多個字符串參數 - opts.alist 如果你想的整數列表,更改解析器類型參數。add_argument爲int

執行結果:

python3.6 temp_agrs1.py -i item5 item6 item7 
    List of items: ['item5', 'item6', 'item7'] 

    python3.6 temp_agrs1.py -i item10 
    List of items: ['item10'] 

    python3.6 temp_agrs1.py 
    List of items: ['item1', 'item2', 'item3'] 
+0

@Py_minion有沒有辦法使用列表作爲參數,並有輸出列表以及? 'temp_args1.py -i [item5,item6,item7]'並且輸出結果也是列表(而不是嵌套列表) – Moondra

+0

@Mondondra是的。很高興你問。 ''' parser.add_argument(' - o','--options',action ='store',dest ='opt_list', type = str,nargs ='*',default = sample_list, help = 「空格分隔的數據庫字符串示例:\ -o option1 option2,-o option3」) ''' 這裏'sample_list'是類型列表的默認選項。例如:sample_list = [option4,option5] –

+0

@Py_minion謝謝。今天晚些時候再測試一下。 – Moondra

2

如果您打算做一臺交換機採用多個參數,然後使用nargs='+'。如果你的榜樣「-L」實際上正在整數:

a = argparse.ArgumentParser() 
a.add_argument(
    '-l', '--list', # either of this switches 
    nargs='+',  # one or more parameters to this switch 
    type=int,  # /parameters/ are ints 
    dest='list',  # store in 'list'. 
    default=[],  # since we're not specifying required. 
) 

print a.parse_args("-l 123 234 345 456".split(' ')) 
print a.parse_args("-l 123 -l=234 -l345 --list 456".split(' ')) 

主要生產

Namespace(list=[123, 234, 345, 456]) 
Namespace(list=[456]) # Attention! 

如果指定相同的參數多次,默認操作('store')替換現有的數據。

另一種方法是使用append動作:

a = argparse.ArgumentParser() 
a.add_argument(
    '-l', '--list', # either of this switches 
    type=int,  # /parameters/ are ints 
    dest='list',  # store in 'list'. 
    default=[],  # since we're not specifying required. 
    action='append', # add to the list instead of replacing it 
) 

print a.parse_args("-l 123 -l=234 -l345 --list 456".split(' ')) 

將會產生

Namespace(list=[123, 234, 345, 456]) 

或者你可以寫一個自定義的處理/動作解析逗號分隔值,這樣你可以做

-l 123,234,345 -l 456 
2

add_argument(),type只是一個可調用的對象,它接收字符串並返回選項值。

import ast 

def arg_as_list(s):                
    v = ast.literal_eval(s)              
    if type(v) is not list:              
     raise argparse.ArgumentTypeError("Argument \"%s\" is not a list" % (s)) 
    return v                 


def foo(): 
    parser.add_argument("--list", type=arg_as_list, default=[], 
         help="List of values") 

這將允許:

$ ./tool --list "[1,2,3,4]" 
+0

請注意,如果需要傳遞字符串,則此方法將要求他們在命令行上適當地引用它們。用戶可能會發現這種意外。如果只解析整數這很好。 – SethMMorton

0

也許最簡單的答案

import argparse 
parser = argparse.ArgumentParser() 
parser.add_argument("-l", "--tolist", help="input to list", action="store_true") 
parser.add_argument("newlist", type=str, help="generate a list") 
args = parser.parse_args() 
if args.tolist: 
    print(args.newlist.split(" ")) 
+0

這假設用戶在每個參數之間用單個空格引用輸入。 – SethMMorton

+0

python test.py -l「265340 268738 270774 270817」 輸入字符串中有單個空格 – FootAdministration

+0

但是,如果用戶意外地放置了兩個空格,則此答案會導致結果中出現錯誤的空字符串。我在說的是,這個答案需要程序員的複雜性,並通過強制他們記住添加引號並確保這些間距是正確的。 – SethMMorton