2017-07-25 3 views
-4

A callee.py hat diese Namespace mit seiner argparse:Wie auf Argarse Schlüsselname statt Wert zugreifen?

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

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

Wenn Sie in der Befehlszeile eingeben, das genug sein sollte:

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

Wenn der Anruf in einem anderen Programm ist caller.py, würde Ich mag an Dazu:

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

Die Vorteile sind: regulierteren einfacher zu aktualisieren, wenn args in callee.py Änderung

Ich wünsche sth kam von argparse oder etwas, das ich mir nicht codieren.

konnte ich sth wie dieses bauen:

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' 

Meine Frage ist: Gibt es einen Weg ins Innere argparse oder andere Art und Weise, die ich nicht eine Klasse für diese bauen müssen?

Dies ist nur ein Beispiel, um die Anforderungen zu erklären, wie dies erreicht werden kann, ist nicht auf argparse beschränkt, wenn Feature nicht verfügbar ist (ich würde davon ausgehen, dass es sollte).

Ich bin sicher, dass ich nicht der erste und letzte bin, der diese Funktion benötigt. Ich hoffe, ich erkläre das diesmal deutlich.

+1

Err, das ist nicht die übliche Art, 'argparse' zu ​​verwenden ... – wim

+1

Was meinst du mit" den Namen bekommen, der Schlüsselaktion ist "? – user2357112

+0

@ user2357112, etwas wie 'parser.action .__ name__' return' action' – Gang

Antwort

2

Die übliche Art, argparse zu verwenden, besteht darin, einen Parser zu definieren, seine 'Argumente' aufzufüllen und parse_args() aufzurufen, um die Befehlszeile zu analysieren.

parse_args() gibt ein Namespace-Objekt zurück, das Sie dann verwenden.

Es ist möglich, ein Namespace-Objekt direkt zu definieren:

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]) 

Sie können die Werte an das bestehende Objekt hinzufügen, aber Sie können nicht Werte zugreifen, die nicht definiert sind. Die Namespace Klasse ist einfach, nur ein paar Methoden hinzufügen, um die Anzeige der Werte schöner zu machen.

Sie können auch ein Wörterbuch von ihm bekommen:

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'] 

Wert Abrufen einer key Zeichenfolge mit:

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

Sie auch Attribute mit Namen

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

Das Set kann Methode, die ns verwendet, um seine Werte anzuzeigen ist:

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__ ist die gleiche Sache vars(ns) gibt. Die Attribute werden in diesem Wörterbuch gespeichert (wie es für die meisten Objekte gilt, insbesondere für benutzerdefinierte Objekte).

Wenn Sie mehr mit Namespace machen oder Ihre eigene Klasse definieren möchten, würde ich vorschlagen, die Klasse in der Datei argparse.py zu betrachten. argparse versucht, minimale Annahmen über die Art dieser Klasse zu machen. Wo es möglich ist, verwendet es die Funktionen getattr und setattr. Und hasattr auch:

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

Von Ihnen bearbeitet es klingt wie Sie wollen ‚erholen‘ die Option Flagge aus den Attributnamen im Namespace. Das ist

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

ein Namespace(foo=..., bar=....)

Das Attribut produzieren Namen der dest genannt wird. Das ist, wenn Werte zu speichern verwendet der Parser

setattr(namespace, dest, value) 

Für ein Positions Argument der dest ist der erste Parameter, ‚bar‘ in dem obigen Beispiel. Für ein optionales Argument wird dest aus dem ersten langen Parameter, dem obigen "- foo", abgeleitet. Oder es kann mit einem expliziten dest='baz' Parameter eingestellt werden.

So einfach einen -- zu dem Schlüssel hinzufügen ist ein Start.

Es gibt keinen Code in argparse, der eine Befehlszeile aus den Analyseergebnissen neu erstellen kann.

+0

zu bekommen, so gibt es keine einfache Möglichkeit, den Namen des Schlüssels zu erhalten, es sei denn, 'argparse' zu ​​ändern, aber es ist möglich, eine Klasse zu erstellen 'ParserKeys' dynamisch mit' vars (parser) .keys() wobei 'ParserKeys.x'' x 'ist? – Gang

+0

Ich verstehe nicht, was Sie mit dem 'Namen des Schlüssels' meinen.'ns' hat Attribute, deren Werte vom Parser gesetzt wurden. Ich habe gezeigt, wie man die Namen dieser Attribute bekommt und wie man sie benutzt, um Werte zu holen. Ich wiederhole, das ist ein einfaches Klassenobjekt. Nichts Außergewöhnliches. – hpaulj

+0

Ihre Änderungen sind immer noch verwirrend, aber ich vermute, dass Sie versuchen, die Befehlszeile aus den Werten im Namespace neu zu erstellen. Das heißt, mappen Sie einen 'Namespace (foo = 'one', bar = 2)' auf die Liste '[' --foo ',' one ',' - bar ',' 2 '] '. – hpaulj