2015-05-14 268 views
4

我試圖做圖像之間的數學運算。我已經定義(簡化了我真正的代碼版本):Argparse:兩個位置參數與nargs ='+'

parser = argparse.ArgumentParser(description='Arithmetic operations on images') 
parser.add_argument("input1", metavar='input1', action='store', 
     help='list of input images to operate with', nargs="+", type=str) 
parser.add_argument("operation", metavar='operation', action='store', type=str, 
     help='type of operation (+,-,*,/) to be done', nargs=1) 
parser.add_argument("input2",metavar='input2', action='store', nargs="+", 
     type=str, help='image (or value) with which to perform the operation on input1') 

此代碼,生產:

arith.py -h 
usage: arith.py [-h] input1 [input1 ...] operation input2 [input2 ...] 

它確實是這樣理解的是輸入1可以包含一個或多個元素,操作將是一個單一的一個,而input2可以是任意數量的元素。

問題當然是,有兩個位置參數與未確定數量的元素,argparse混淆了什麼是什麼。我嘗試在'操作'中添加選項= [「+」,「 - 」,「*」,「/」],以便它知道在哪裏做分離,但似乎argparse無法做到。實際上,argparse文檔中,談到NARGS =「*」你可以閱讀:

需要注意的是,一般沒有太大的意義,有NARGS =不止一個位置參數「*」

我以爲我可以將args.input1,args.operation和args.input2加在一起,並將自己分開尋找「+」,「 - 」,「/」,「*」,但在做一件非常醜陋的事情之前,我會想想要挖掘集體思想。

+2

我不確定''argparse'是否適合你在這裏做什麼。直接通過'sys.argv'可能會更容易。 – khelwood

+0

嗨khelwood。實際上,我使用argparse解析sys.argv。這爲我提供了「免費」的幫助,它爲我完成了所有的檢查類型和現有變量。直接執行sys.argv就像我的解決方案,將input1,operation和input2集中到一起,然後分離出我自己。可行,但醜陋;)。不管怎麼說,還是要謝謝你! – Jblasco

+0

'argparse'可以構造這樣的幫助信息,但這並不意味着它實際上可以按照你想要的方式解析參數。如果我叫'arith.py a b c d e f g',哪一個是'operation'?它可以是'b'到'f'中的任何一個。 'argparse'沒有任何內置的回溯模式匹配器;它只是以一種貪婪的方式處理從左到右的爭論。 – chepner

回答

0

如果您使用「必需的可選」參數,您可以使這項工作。如果需要命令行上的選項來顯示從左操作數切換到操作時更改爲正確的操作數。例如。其餘的 -

import argparse 

parser = argparse.ArgumentParser(description='Process some integers.') 
parser.add_argument("--left-operands", "-l", nargs="+", required=True) 
parser.add_argument("--right-operands", "-r", nargs="+", required=True) 
parser.add_argument("--operation", "-o", choices=["+", "-", "*", "/"], required=True) 

argline = "-l 1 2 -o + -r 3 4" 

print(parser.parse_args(argline.split(" "))) 
+0

謝謝,沙丘,但不是我正在尋找的東西。我希望這些論據是位置的。否則,我將回到將輸入1,輸入2和操作放在一起並將它們在內部分開的想法。 – Jblasco

1

當分配字符串positionals,解析器只有那些用一個前綴字符(「」例如)開始之間進行區分。它無法區分表示「數字」的字符串和表示「操作」的字符串。實際上,它執行此正則表達式操作:

re.match('(A+)(A)(A+)','AAAAAAAAA') 

這將產生(AAAAAA),(A),(A)。它爲最後兩組分配足夠的字符串以滿足其規格,並將其餘的分配給第一組。

所以你需要某種'標誌'來標記第一個列表的結束。

這是,我認爲,最接近你會得到​​:

parser.add_argument("input1", nargs="+", type=int) 
parser.add_argument("-o", "--operation", choices=['+','minus','*','/']) 
parser.add_argument("input2", nargs="+", type=int) 

應該把

PROG 1 3 4 -o + 5 6 7 
PROG 1 3 4 -o+ 5 6 7 
PROG 1 3 4 --operation=+ 5 6 7 

到(我認爲)

namespace(input1=[1,3,4], operation='+', input2=[5,6,7]) 

注意choices的列表不包括' - '。這是因爲解析器將它視爲prefix_char。可能有偷偷摸摸的方式作爲參數價值,但我不會花時間來找到它。

我在解析器中將input1的值轉換爲整數。之後你可以做到這一點。當然,製作花車代替。

我省略了默認參數,如type=str,action='store'


但也許更好的解決方案是將所有的值作爲1列表,並自己分裂。至少有了這3個參數,你沒有太多的使用權力。

alist = ['1','2','3','+','4','5','6'] 
i = <find index of '+-/*'> 
input1 = alist[:i] 
operations = alist[i] 
input2 = alsits[i+1:] 
+0

感謝您的努力。在過去,我已經能夠將一個「 - 」變成一個非定位參數的唯一方法是: -o「 - 」 所以一個字符串前面有一個空格,所以 - 被視爲字符串的一部分 – Jblasco

+0

將'#'指定爲prefix_char,可以釋放'-'作爲參數。 – hpaulj

+0

是的,hpaulj,這是我遵循的方法,正如我在OP中暗示的那樣。看起來我太過分了。不過,我只是留下了三個論點,爲了讓用戶清楚起見。解析後,我再次加入並正確分割它們。 – Jblasco