argparse module - eine default Textdatei setzen, falls kein Argument via "command line" mitgegeben wird

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
GabrielleChanel
User
Beiträge: 42
Registriert: Dienstag 13. April 2021, 11:54

Ziel: Ich würde gerne via "command line" entweder genau eine Textdatei (optional) oder wenn kein Argument mitgegeben wird ("command line" ohne Argument) eine "default" Textdatei verwendet wird (hier "words.txt"). Wie kann ich eine "default" Textdatei mit "argparse" erstellen?

#my_program.py
import argparse

parser = argparse.ArgumentParser(description = "macht etwas")
parser.add_argument('-f', '--textfile', type = str, nargs = '+', help = "obligatorisch: nimmt 1 oder mehrere Textdateien als Argument", required = True) #diese Zeile funktioniert schon

#die folgende Zeile funktioniert noch nicht:
parser.add_argument('-w', '--words', type = str, nargs = 1, default = '/data/words.txt', help = "optional: kann nur ein Argument nehmen, wenn keines gegeben ist wird by default 'words.txt' als Argument verwendet.", required = False)

args = parser.parse_args()

##um diese Funktion aufzurufen (python my_program.py -flags 'files' -flags 'files'):
#python my_program.py -f 'my_path\textfile_1.txt' -w 'my_other_path\other_words.txt' #hier mit einer Inputtextdatei bei '-w' flag, also wird die "other_words.txt" Datei statt der default "words.txt" Textdatei verwendet
#python my_program.py -f 'my_path\textfile_1.txt' #hier ohne '-w' flag, also sollte die default Textdatei "words.txt" verwendet werden.
Benutzeravatar
__blackjack__
User
Beiträge: 13122
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@GabrielleChanel: Das ist ein bisschen komisch. Erst einmal sollte es keine `required` *Optionen* geben. Das ist ein Widerspruch das etwas obligatorisches optional ist. Dann ist das "+" bei `nargs` schlecht bis falsch, weil das verwirrend ist. Bei ``programm -f foo.txt bar.txt -w extra_words.txt`` ist dann nicht mehr wirklich klar ob das jetzt zwei Werte bei -f sind, oder vier und ``-w`` und ``extra_words.txt`` Werte sind die zum ``-f`` gehören. Das ``-f`` sollte es nicht geben, das sind einfach Positionsargumente von denen es mindestens eines geben muss.

Das Optionen kein oder 1 Argument nehmen ist der Normalfall, man braucht da weder `nargs` übergeben noch das extra im Hilfstext erwähnen. Wenn ein Argument erwartet wird, dann steht in der generierten Hilfe an der Stelle ein beschreibender Name für dieses Argument, falls kein Argument erwartet wird, steht in der generierten Hilfe nur die Option.

Code: Alles auswählen

#!/usr/bin/env python3
import argparse


def main():
    parser = argparse.ArgumentParser(description="macht etwas")
    parser.add_argument(
        "-w", "--words", default="/data/words.txt", help="default: %(default)s"
    )
    parser.add_argument(
        "text_files", metavar="FILE", nargs="+", help="input files"
    )
    args = parser.parse_args()
    print(args)


if __name__ == "__main__":
    main()
Wobei ich persönlich hier "*" statt "+" verwenden würde und falls keine Eingabedatei angegeben wurde, die Standardeingabe lesen würde. Dann lässt sich das Programm auch in Pipelines benutzen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
GabrielleChanel
User
Beiträge: 42
Registriert: Dienstag 13. April 2021, 11:54

Vielen Dank für deine Inputs und Ausführungen. Zwei Dinge möchte ich jedoch noch erwähnen, um auch klarzustellen, ob ich alles richtig verstanden habe:

- Einerseits ist klar welche Dateien zu -f und welche zu -w gehört, weil immer der Flag und anschliessend alle Dateinamen kommen. D.h.: python my_program.py -f datei_1.txt datei_2.txt datei_3.txt -w word_1.txt "-f" kann einfach mindestens eine oder mehrere (n-Anzahl) Dateien enthalten, während "-w" optional ist und bei Erwähnung die darauffolgende eine Datei verwendet wird und sonst eine Defaultdatei. Die Argumente sind gewollt nicht an ihre Position gebunden (sodass nicht eine bestimmte Eingabereihenfolge beachtet werden muss), d.h. die Flags sind notwendig und entscheiden über die weiteren Schritte (wie die Dateien verarbeitet werden sollen).

- Der zweite Punkt, der noch offen steht: wie kann ich eine Datei als Default setzen, genügt es: ... default="/data/words.txt" zu schreiben? Wird dann bei keiner "-w word_1.txt"-Eingabe die "/data/words.txt"-Datei genommen? Und bei der Eingabe "-w word_1.txt"-Eingabe wird die "word_1.txt" statt der "/data/words.txt" Datei genommen? Habe ich dies richtig verstanden?

Vielen Dank im Voraus für deine Auskunft und Hilfe.
"Those who can imagine anything, can create the impossible." Alan Turing
Benutzeravatar
__blackjack__
User
Beiträge: 13122
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@GabrielleChanel: So klar ist das nicht, das muss man erst nachlesen oder ausprobieren ob "-w" eine Option oder ein Dateiname ist. Es ist eine Option. Aber so selbstverständlich ist das nicht. Es ist halt verwirrend. Weil kein anderes Programm das so macht. Wenn Du jemanden Fragst was für Optionen und Argumente der folgende Aufruf hat:

program.py datei_1.txt datei_2.txt datei_3.txt -w word_1.txt

werden so ziemlich *alle* die das lesen, sagen das mindestens "datei_2.txt" und "datei_3.txt" nicht zu den Optionen gehören sondern Positionsargumente sind. Das ist einfach superungewöhnlich das so zu machen, und ich sehe auch keinen guten Grund das so zu machen. Die Reihenfolge ist durch Positionsargumente auch nicht vorgeschrieben. ``./program.py a.txt b.txt -w extra_words.txt`` geht genau so wie ``./program.py -w extra_words.txt a.txt b.txt``.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
GabrielleChanel
User
Beiträge: 42
Registriert: Dienstag 13. April 2021, 11:54

Vielen Dank für deine letzte Nachricht, jetzt verstehe ich auch die vorherigen Aussagen. Ich hatte ein Durcheinander mit dem "-"Flag Symbol, d.h.:
"textfile" #Pflichtargument (und nicht "--textfile" ansonsten wäre es optional und zusätzlich mit dem "required = True" hätte ich diese Zeile zu einem absurden "optionalen Argument als Pflichtargument" gemacht)
"--words" #optionales Argument
"-w" #optionales Argument als Abkürzung
Und so macht nun alles was du vorhin erklärt hast einen Sinn, vielen herzlichen Dank für deine Hilfe :)
"Those who can imagine anything, can create the impossible." Alan Turing
Antworten