2011-10-12 61 views
2

我想知道如何從命令行傳遞的可選參數的順序argparse爲了蟒蛇+ argparse - 如何得到的命令行的可選參數

我有圖像處理類,這是能夠運用不同的操作圖像 - 像旋轉,​​裁剪,調整大小...

和秩序,這些動作被應用往往是必要的(例如:你想你調整它之前裁剪圖像)

我有這樣的代碼:

parser = argparse.ArgumentParser(description='Image processing arguments') 

parser.add_argument('source_file', help='source file') 
parser.add_argument('target_file', help='target file') 

parser.add_argument('-resize', nargs=2, help='resize image', metavar=('WIDTH', 'HEIGHT')) 
parser.add_argument('-rotate', nargs=1, help='rotate image', metavar='ANGLE') 
parser.add_argument('-crop', nargs=4, help='crop image', metavar=('START_X','START_Y','WIDTH','HEIGHT')) 

ar = parser.parse_args() 

print ar 

但是 - 無論在哪個順序我將參數傳遞給腳本:

cmd.py test.jpg放在test2.jpg -crop 10 10 200 200 450調整大小300

cmd.py測試.JPG test2.jpg調整大小450 300 -crop 10 10 200 200

在命名空間的項目總是在相同的順序(按字母我想):

Namespace(crop=['10', '10', '200', '200'], resize=['450', '300'], rotate=None, source_file='test.jpg', target_file='test 
2.jpg') 

有辦法按命令行字符串中的位置對它們進行排序或獲取它們的索引嗎?

回答

4

你可以在sys.argv總是偷看這是一個列表(因此命令),並簡單地遍歷它檢查哪個參數是第一位的,或使用list.index()看到列表中的關鍵字各自的立場...

sys.argv包含在命令行中輸入的單詞列表(除非字符串被引號包圍,否則此「單詞」的分隔符是空格)。這意味着如果用戶輸入類似./my_proggie -resize 500的東西,則sys.argv將包含如下列表:['./my_proggie', '-resize', '500']

2

命名空間是一個簡單的對象,其str()根據它的__dict__中的鍵的順序列出其屬性。屬性設置爲setattr(namespace, dest, value)

一個解決方案是定義一個自定義命名空間類。例如:

class OrderNamespace(argparse.Namespace): 
    def __init__(self, **kwargs): 
     self.__dict__['order'] = [] 
     super(OrderNamespace, self).__init__(**kwargs) 
    def __setattr__(self,attr,value): 
     self.__dict__['order'].append(attr) 
     super(OrderNamespace, self).__setattr__(attr, value) 

並使用

args = parser.parse_args(None, OrderNamespace()) 

製造用於您的兩個例子

OrderNamespace(crop=..., order=[..., 'crop', 'resize'], resize=...) 
OrderNamespace(crop=..., order=[..., 'resize', 'crop'], resize=...) 

order屬性給出,其中其它屬性被設置的順序。最初的項目是默認值和文件位置。將參數default=argparse.SUPPRESS添加到參數將會抑制這些項目中的一部分。這個自定義類可能更精細,例如使用OrderedDictionary,只記錄所選參數的順序,或者使用order來控制屬性的顯示。

另一種選擇是使用創建此order屬性的自定義操作類,例如,

class OrderAction(argparse._StoreAction): 
    def __call__(self, parser, namespace, values, option_string=None): 
     setattr(namespace, self.dest, values) 
     order = getattr(namespace, 'order') if hasattr(namespace, 'order') else [] 
     order.append(self.dest) 
     setattr(namespace, 'order', order) 
+0

OrderNamespace是一個很好的解決方案,如果一個人也想使用其他操作(例如builtins)。好想法! –

+0

不幸的是,當設置了默認值時,將調用所有默認值的__setattr__方法,但是它們是否被使用。 –

+0

如果您不使用'SUPPRESS',默認值將出現在'訂單'列表的開頭,也可能在結尾處再次出現。 'parser'使用相同的'__setattr__'來記錄默認值和給定值。 'OrderAction'沒有這個問題。 – hpaulj

1

我改編自hpaulj的辦法:

class OrderNamespace(argparse.Namespace): 
     def __init__(self, **kwargs): 
      self.__dict__['order'] = [] 
      super(OrderNamespace, self).__init__(**kwargs) 
     def __setattr__(self,attr,value): 
      if value: 
       self.__dict__['order'].append(attr) 
      super(OrderNamespace, self).__setattr__(attr, value) 


    parser.add_argument('-g',action='append',default=argparse.SUPPRESS,help='some action') 

通過添加「如果值:」 ......你只能得到每一個使用的說法正確的次數。

+0

這個效果更好 – ddofborg