Hallo,
habe mich gerade in der Dokumentation von optparse reingelesen - klasse Sache. Nun parst das Modul aber offenbar nur die dem Pythonprogramm via Kommandozeile übergeben Parameter. Wie kann man mit optparse auch andere Strings parsen?
Der Hintergrund ist der, daß ich für mein Programm eine Konfigurationsdatei haben möchte, wo der Benutzer Optionen, die er nicht jedesmal neu beim Programmstart angeben will, hineinschreiben kann. Freilich läßt sich das mit einer eigenen Syntax lösen, aber zweckmäßiger Weise soll der Benutzer die Optionen einfach genauso in die Datei reinschreiben, wie er sie normalerweise auf der Kommandozeile eingeben würde.
Den Dateiinhalt einfach mit der split-Funktion an den Leerzeichen aufteilen (um dann einfach getopt zu verwenden) geht nicht, da man ja auch Argumente mit Leerzeichen (entweder maskiert mit Backslash oder aber in Gänsefüßchen) eingeben können soll.
Die Alternative wäre, daß der Benutzer sich ein eigenes Startskript mit seinen gewünschten Optionen schreibt, aber das wäre mir - gerade als Pythonprogrammierer - doch zu unelegant (zumal dann noch die Daten des Standardeingabekanals weitergeleitet werden müßten).
Danke für alle kreativen Inputs!
Rajmund
Dateiinhalt mit optparse parsen
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hi Rajmund!Rajmund hat geschrieben:Wie kann man mit optparse auch andere Strings parsen?
Das ist zwar möglich, indem man die Argumente an **parser.parse_args()** direkt übergibt, aber nicht gerade einfach. Wie du schon bemerkt hast, kann man nicht einfach einen String übergeben, sondern man muss sich selber um Anführungszeichen usw. kümmern. Siehe: http://docs.python.org/lib/optparse-par ... ments.html
Die andere Variante ist die, dass du die Standardwerte der Optionen setzt. Du kannst also die Standardwerte in eine einfache INI-Datei schreiben (lassen) und **optparse** damit füttern.
Siehe:
http://docs.python.org/lib/optparse-par ... ments.html
http://docs.python.org/lib/module-ConfigParser.html
Hier ein Beispiel:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from ConfigParser import SafeConfigParser
from optparse import OptionParser
CONFIG_FILENAME = "config.ini"
def write_ini(filename):
"""
Schreibt etwas in die INI-Datei
"""
ini = SafeConfigParser()
ini.add_section("MAIN")
ini.set("MAIN", "debug", "True")
ini.set("MAIN", "iterations", "14")
f = file(filename, "w")
ini.write(f)
f.close()
def get_ini_object(filename):
"""
INI-Datei auslesen und als Objekt zurück geben
"""
ini = SafeConfigParser()
ini.read(filename)
return ini
#----------------------------------------------------------------------
def parse_options(ini = None):
"""
Wertet die Argumente aus und gibt diese zurück
"""
# Parser-Objekt erzeugen und Optionen hinzufügen
parser = OptionParser()
parser.add_option(
"--iterations",
dest = "iterations",
action = "store",
default = 3,
metavar = "COUNT",
help = "COUNT ist die Anzahl der Durchlaeufe."
)
parser.add_option(
"-d", "--debug",
dest = "debug",
action = "store_true",
default = False,
help = "show debug messages"
)
# Standardwerte hinzufügen
if ini:
if ini.has_option("MAIN", "debug"):
parser.set_default("debug", ini.getboolean("MAIN", "debug"))
if ini.has_option("MAIN", "iterations"):
parser.set_default("iterations", ini.getint("MAIN", "iterations"))
# Optionen parsen
(options, args) = parser.parse_args()
# Optionen und Argumente anzeigen
if options.debug:
print "Options:"
print options
print "-"*70
print "Arguments:"
print args
# Optionen zurück geben
return (options, args)
if __name__ == "__main__":
write_ini(CONFIG_FILENAME)
ini_object = get_ini_object(CONFIG_FILENAME)
(options, args) = parse_options(ini_object)
# Ab hier können die Optionen verwendet werden.
Gerold
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Hi gerold,
prima, Danke! Das ist natürlich auch eine schöne Lösung.
Ich hab mich nun doch hingesetzt und einen kleinen Parser getippt, der mir Kommandozeilenargumente aus beliebiger Quelle (eben z.B. aus einer Datei) so zerhackt und in eine Liste packt, daß ich sie an getopt geben kann. War nicht schwer (ich wahr eigentlich nur zu faul und dachte, es ginge einfacher ). Zwar kann ich jetzt optparse nicht nutzen, aber für meine Zwecke reicht auch erstmal getopt.
Verbesserungsvorschläge sind gerne willkommen!
Grüße
Rajmund
prima, Danke! Das ist natürlich auch eine schöne Lösung.
Ich hab mich nun doch hingesetzt und einen kleinen Parser getippt, der mir Kommandozeilenargumente aus beliebiger Quelle (eben z.B. aus einer Datei) so zerhackt und in eine Liste packt, daß ich sie an getopt geben kann. War nicht schwer (ich wahr eigentlich nur zu faul und dachte, es ginge einfacher ). Zwar kann ich jetzt optparse nicht nutzen, aber für meine Zwecke reicht auch erstmal getopt.
Code: Alles auswählen
def splitopt(arg):
"""Splitter, berücksichtigt Anführungszeichen und Maskierungen.
"""
Masksymbols = [" ","'", '"', "\\", ";"]
l = len(arg)
i = 0 # i ist unser "Cursor"
start = 0
result = [] # hier kommen die Tokens dann hinein
while i < l:
while i < l and arg[i] == " ": i += 1 # Leerzeichen überspringen
start = i
if arg[i] == "'": # Zeichenketten in ' auslesen
i += 1
while i < l and arg[i] != "'": i += 1 # bis zum Ende der Zeichenkette gehen
result.append(arg[start+1:i]) # den Teil herauslösen und in Ergebnisliste hinein
i += 1
elif arg[i] == '"': # Zeichenketten in " auslesen, funktioniert wie oben
i += 1
while i < l and arg[i] != '"': i += 1
result.append(arg[start+1:i])
i += 1
else: # ansonsten normale durch Leerzeichen begr. Tokens auslesen
resultstr = "" # wegen der \-Maskierungen brauchen wir einen Zwischenspeicher
while i < l and arg[i] != ' ':
if i+1 < l and arg[i] == "\\" and arg[i+1] in Masksymbols: # sind wir auf nen Backslash mit einem Spezialzeichen dahinter
i+=1 # dann den Cursor i gleich auf dieses Zeichen setzen
resultstr += arg[i] # das Zeichen über dem Cursor in den Ergebnisstring hinein
i += 1 # Cursor an nächste Position
result.append(resultstr) # Ergebnisstring abspeichern
return result
Grüße
Rajmund
Schau mal ob Dir das `shlex` Modul nicht das lästige Parsen von Zeichenketten in Anführungszeichen usw. abnehmen kann.
Hab mir shlex mal kurz angesehen - würde sicher auch gehen. Danke!