2017-07-25 14 views
-4

一個callee.py有這個Namespace使用其​​:如何訪問argparse鍵名稱而不是值?

parser = Namespace(action='run', action_area='park', severity='high') 

In [30]: parser.action 
Out[30]: 'run' 

如果在命令行中鍵入,這已經足夠了:

callee.py --run --action_area gym --severity low 

如果調用其他程序caller.py裏面,我想做到這一點:

callee.py sth.run sth.action_area 'gym' sth.severity 'low' 

的優點是: 更規範 更容易更新,如果在callee.py變化

ARGS我希望sth從​​什麼的,我沒有對自己的代碼來了。

我可以建立sth這樣的:

class ParserKeys(object): 
    def __init__(self, keys): 
     self.keys = keys 
     for key in keys: 
      setattr(self, key, '--{0}'.format(key)) 

sth = ParserKeys(vars(parser).keys()) 

In [91]: sth.action 
Out[91]: '--action' 

我的問題是:是否有內,我沒有建立這個類​​或其他方式的方法嗎?

這只是一個例子來解釋的要求,如果功能不可用(如果我認爲它應該),如何實現這個不限於​​。

我確定我不是第一個也是最後一個需要此功能的人。我希望我這次清楚地解釋一下。

+1

錯誤,這不是使用'argparse'的常見方法... – wim

+1

你甚至認爲「獲取關鍵行爲的名稱」是什麼意思? – user2357112

+0

@ user2357112,類似於'parser.action .__ name__'返回行動' – Gang

回答

2

使用​​的常用方法是定義解析器,填充其「參數」,並調用parse_args()來解析命令行。

parse_args()返回您隨後使用的Namespace對象。

它可以直接定義命名空間對象:

In [203]: ns = argparse.Namespace(x=12, y='abc') 
In [204]: ns 
Out[204]: Namespace(x=12, y='abc') 
In [205]: ns.x 
Out[205]: 12 
In [206]: nx.z 
.... 
NameError: name 'nx' is not defined 
In [207]: ns.z = [1,2,3] 
In [208]: ns 
Out[208]: Namespace(x=12, y='abc', z=[1, 2, 3]) 

可以將值添加到現有的對象,但你不能訪問是沒有定義的值。 Namespace類很簡單,只需添加一些方法來顯示更漂亮的值。

你也可以從它那裏得到一本字典:

In [209]: vars(ns) 
Out[209]: {'x': 12, 'y': 'abc', 'z': [1, 2, 3]} 

In [210]: list(vars(ns).keys()) 
Out[210]: ['z', 'y', 'x'] 

抓取使用key字符串值:

In [212]: getattr(ns,'x') 
Out[212]: 12 

您也可以按名稱設置屬性

In [220]: setattr(ns,'w','other') 
In [221]: ns 
Out[221]: Namespace(w='other', x=12, y='abc', z=[1, 2, 3]) 

ns用於顯示其值的方法是:

def __repr__(self): 
    type_name = type(self).__name__ 
    arg_strings = [] 
    for arg in self._get_args(): 
     arg_strings.append(repr(arg)) 
    for name, value in self._get_kwargs(): 
     arg_strings.append('%s=%r' % (name, value)) 
    return '%s(%s)' % (type_name, ', '.join(arg_strings)) 

def _get_kwargs(self): 
    return sorted(self.__dict__.items()) 

self.__dict__是一回事vars(ns)給出。這些屬性存儲在這個字典中(對於大多數對象,尤其是用戶定義的對象)。

如果你想用Namespace做更多,或者定義你自己的班級,我建議你看看argparse.py文件中的班級。​​試圖對這個類的本質做出最少的假設。它儘可能使用getattrsetattr函數。而hasattr還有:

In [222]: hasattr(ns, 'foo') 
Out[222]: False 
In [223]: hasattr(ns, 'w') 
Out[223]: True 

從你編輯它聽起來像你想從命名空間中的屬性名稱,以「恢復」的選項標誌。也就是說

parser.add_argument('--foo', '-f', ...) 
parser.add_argument('bar', ...) 
parser.add_argument('--other', dest='baz',...) 

會產生Namespace(foo=..., bar=....)

屬性的名字叫做dest。即保存值當解析器使用

setattr(namespace, dest, value) 

對於一個位置參數的dest是在上面的例子中第一參數,「酒吧」。對於可選參數,dest從第一個長參數,即上面的' - foo'派生。或者可以使用明確的dest='baz'參數進行設置。

因此,簡單地將--添加到ns.__dict__密鑰是一個開始。

​​中沒有任何可以從解析結果重新創建命令行的代碼。

+0

所以沒有簡單的方法來獲得鍵的名稱,除非改變'argparse',但可以建立一個類'ParserKeys'動態使用'vars(parser).keys()其中'ParserKeys.x'是'x'? – Gang

+0

我不明白你的意思是'鑰匙的名字'。'ns'具有屬性,其值由解析器設置。我展示瞭如何獲取這些屬性的名稱,以及如何使用它們來獲取值。我會重複一遍,這是一個SIMPLE類對象。沒有什麼花哨。 – hpaulj

+0

您的編輯仍然令人困惑,但我猜測您正嘗試從命名空間中的值重新創建命令行。也就是說,將名字空間(foo ='one',bar = 2)'映射到'['--foo','one','--bar','2']'列表。 – hpaulj

相關問題