argparse mit zwei input listen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

Hallo,

ich möchte mit argparse prüfen ob input und output definiert sind.
Dabei kann der input eine Liste an Dateien sein.
Dies würde ich folgender maßen bewerkstelligen:

Code: Alles auswählen

#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-i_s','--input_single', help='Input file name',required=True,nargs='+')
parser.add_argument('-o','--output',help='Output file name', required=True)
args = parser.parse_args()
print ("Input file: %s" % args.input_single )
print ("Output file: %s" % args.output )
So ich möchte eine weitere input Liste mit Dateien angeben.
dann würde ich einfach erweitern wie im folgendem:

Code: Alles auswählen

#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-i_s','--input_single', help='single Input file name',required=True,nargs='+')
parser.add_argument('-i_m','--input_multiple', help='multiple Input file name',required=True,nargs='+')
parser.add_argument('-o','--output',help='Output file name', required=True)
args = parser.parse_args()
print ("Input file: %s" % args.input_single )
print ("Output file: %s" % args.output )
1. Frage:
Ich würde jetzt gerne die Prüfung so erweitern das das script nur mit [-i_s] oder nur mit [-i_m] oder mit [-i_s und -i_m] gestartet werden kann.
2.Frage:
Danach möchte ich zu den jeweiligen Listen eine parameter Liste angeben. Also wenn -i_s dann muss -i_s_parameter gesetzt sein und usw.

Kann mir da jemand helfen?

Für entweder -i_s oder -i_m habe ich diesen Ansatz gefunden:

Code: Alles auswählen

#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('-i_s','--input_single', help='single Input file name',nargs='+')
group.add_argument('-i_m','--input_multiple', help='multiple Input file name',nargs='+')
parser.add_argument('-o','--output',help='Output file name', required=True)
print parser.parse_args()
Aber die input parameter dürfen nur noch optional sein und halt entweder oder. Kann ich das über den namespace lösen? Wenn ja wie gehe ich das an?
BlackJack

@airtime: Komplexere Bedingungen würde ich einfach nach dem Parsen mit Code prüfen.

'-i_s' und '-i_m' würde ich als Fehler ansehen. Optionale Argumente mit einem '-' dürfen auch nur ein Buchstabe lang sein. Das erwartet der Benutzer so weil das alle so machen. Alles was länger als ein Buchstabe ist beginnt mit '--'.
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

@BlackJack: Der Vorteil von argparse ist ja, das das script nur gestartet wird wenn definierte parameter gesetzt sind.
Wenn ich jetzt hinter her prüfe ob die entsprechenden parameter gesetzt sind brauche ich argparse nicht.
Ich hatte zu erst damit begonnen die Prüfung selbst durch zu führen, aber mit argparse kann ich mir viel code und unvorhergesehene eingaben sparen.
Aber das ist alles Ansichstsache.

Bei -i_s und -i_m handelt es sich ja nicht um optionale argumente, ich musste sie nur als optional definieren um das mutual exclusive beispiel durchführen zu können (Das war nur als Beispiel was ich bisher hingekriegt habe).
Meine Frage war wie definiere ich das entweder -i_s oder -i_m oder beide gesetzt werden müssen.
Also es muss mindestens einer gesetzt werden, aber es können auch beide gesetzt werden.
Ich habe keine Erfahrung mit argparse deswegen bin ich für alle Lösingsvorschläge offen.
Vielleicht ist auch meine Herangehensweise falsch, ich denke man könnte auch ein reqiured input argument mit -i definieren und eine type angabe erwarten wie single oder multiple, aber wie mache ich das mit argparse?
Vielleicht parent und child?
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@airtime: was ist denn der Unterschied zwischen single-Input und multiple-Input? Kann man das einfach am Dateiformat unterscheiden. Dann würde ich nämlich gar keine eigenen "optionalen" Parameter für Inputs nehmen, denn Inputs werden üblicherweise ohne "-"-Option angegeben.
BlackJack

@airtime: Der Vorteil von `argparse` ist das einem eine ganze Menge Code zum Verarbeiten von Kommandozeilenargumenten abgenommen wird, unter anderem Typumwandlungen, *einfache* Prüfungen, und das generieren von Hilfetexten. Aber das kann man natürlich weglassen wenn es nicht möglich ist das `argparse` irgendwelche wilden Interoptionen-Bedingungen prüfen kann. Dann ist es natürlich total überflüssig. ;-)

Okay, dann streich das ”optional” aus der Aussage: Wenn es mit *einem* '-' beginnt, darf es nur *einen* Buchstaben lang sein. Der Benutzer erwartet das so. Wenn da mehrere stehen dann lesen die meisten Benutzer ``-abc`` als ``-a -b -c`` und `argparse` unterstützt das auch. Wenn es jetzt kurze Optionen gibt die mehr als ein Zeichen lang sind, wird es verwirrend.

Lösungsvorschlag bleibt weiterhin: Teste das einfach nach dem Parsen.
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

Sorry anscheinend habe ich wieder zu wenig Informationen gegeben.

@BlackJack vielen dank für die Info der Konventionen, damit bin ich nicht so sehr vertraut. Also werde ich meine argument kennungen kürzen. Das eigene Prüfen möchte ich gerne umgehen.

@Sirius3 Der unterschied ist das ich aus single dateien weniger info bekomme und bei multiple mehr, das werde ich aber gleich nochmal versuchen genauer zu erklären. Die input option ist normalerweise ohne option gegeben aber ich möchte sowohl zwischen den zwei dateien unterscheiden als auch die möglichkeit geben mehrere dateien eines typs einlesen zu können.

Ok ich versuche nochmal meine Frage anders zu formulieren:
Also als Eingabe/Input können mehrere Dateien angegeben werden, deswegen habe ich nargs='+' mit angegeben. Da ich aber zwei verschiedene Dateiarten(nicht äußerlich unterscheidbar) verarbeiten möchte, würde ich die dateiart mit angeben(Der user weiß welche Dateien single und welche multiple sind). Also die Ausführung sollte dann so aussehen:

Code: Alles auswählen

python -s file1 file2 file3 file4 ... -m file1 file2 file3 ... -o output.txt
Jetzt möchte ich gerne mit argparse definieren das mindestens eine Dateiart angegeben werden muss, es aber auch beide geben darf. Wie müsste ich das angehen?

Wenn diese Prüfung fertig ist würde ich gerne noch zusätzliche Angaben zu den Dateiarten machen, da die Dateien unterschiedlich verarbeitet werden. Das heißt bei single muss das argument -single_parameter [1,2,3] angegeben werden und bei multiple das argument -multiple_parameter [1,2,3,4,5] und das nur wenn die jeweiligen Dateiarten angegeben wurden.

Vielen Dank für eure Hilfe, ich hoffe ich konnte meine Frage jetzt besser beschreiben.
BlackJack

@airtime: Die Antwort bleibt die selbe: Teste das nach dem Parsen. Echt jetzt, das sind zwei Zeilen Code, ein ``if`` mit einem popelig einfachen Test und die Fehlermeldung über das `ArgumentParser`-Objekt. Warum sträubst Du Dich da so hartnäckig gegen?

Was immer Du mit `argparse` anstellst es kann nicht einfacher werden als das folgende, falls es überhaupt möglich ist einen Parser zu erzeugen der das testet:

Code: Alles auswählen

    if not (options.single_input or options.multiple_input):
        parser.error('at least single or multiple input must be given')
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

@BlackJack Jetzt verstehe ich was du meinst, ich dachte die ganze Prüfung soll ich durchführen. Sorry für das Missverständnis.

Aber wie verbinde ich jetzt die argumente -s mit --single_parameter und -m mit --multiple_parameter?
Oder kann ich einer Struktur aufbauen z.B: s- [[parameter1,parameter2,...] [file1,file2,...]] ?
BlackJack

@airtime: Schau Dir mal die `zip()`-Funktion an. Gegebenfalls auch `itertools.izip()` bei Python 2.
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@airtime: heißt das, dass zu jeder Inputdatei ein Parameter gesetzt werden muß? Da würde ich auf jeden Fall eine Struktur "parameter1 file1 parameter2 file2" wählen und die gegebenenfalls auch außerhalb von argparse prüfen.
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

@BlackJack ok da schau ich mal nach. Die methode wird ja zur vereinigung von listen genutzt aber inwiefern das mir bei meinem pProblem hilft muss ich nochmal überlegen. Danke

@Sirius3 Nein keine Paarbildung. Ich habe eine feste parameterfolge für single und eine feste Parameterfolge für multiple also -s [[parameterfolge_für_alle_single] [files]] und -m [[parameterfolge_für_alle_multiple] [files]]
BlackJack

@airtime: Du willst also Parameter und Dateinamen mit *einer* Option angeben? Wie kann man denn da Unterscheiden wo die Parameter aufhören und die Dateinamen anfangen? Ich würde ja für die Parameter eine eigene Option verwenden.
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

@BlackJack Ja dann muss ich aber die option mit den parametern als required angeben wenn die jeweiligen Dateien angegeben werden. Wie geht das? nur required dann wird die option immer erwartet.
BlackJack

@airtime: Naja auch wieder danach prüfen ob wenn das eine angegeben ist auch das andere angegeben ist. Die API wird IMHO immer komischer. Das wird mittlerweise so kompliziert das ich das mit den Dateien und den Parametern wahrscheinlich gar nicht mehr über Optionen regeln würde sondern eine Konfigurationsdatei vom Benutzer verlangen würde.
airtime
User
Beiträge: 23
Registriert: Donnerstag 23. August 2012, 12:52

ok ich probiere dann mal aus was ich hinkriege. Vielen Dank für Eure Hilfe
Antworten