Dateiinhalt mit optparse parsen

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
Rajmund
User
Beiträge: 3
Registriert: Freitag 9. Juni 2006, 23:29
Wohnort: Leipzig
Kontaktdaten:

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
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Rajmund hat geschrieben:Wie kann man mit optparse auch andere Strings parsen?
Hi Rajmund!

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.
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Rajmund
User
Beiträge: 3
Registriert: Freitag 9. Juni 2006, 23:29
Wohnort: Leipzig
Kontaktdaten:

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.

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
Verbesserungsvorschläge sind gerne willkommen!
Grüße
Rajmund
BlackJack

Schau mal ob Dir das `shlex` Modul nicht das lästige Parsen von Zeichenketten in Anführungszeichen usw. abnehmen kann.
Rajmund
User
Beiträge: 3
Registriert: Freitag 9. Juni 2006, 23:29
Wohnort: Leipzig
Kontaktdaten:

Hab mir shlex mal kurz angesehen - würde sicher auch gehen. Danke!
Antworten