Seite 1 von 1

replace problem

Verfasst: Donnerstag 7. April 2011, 15:39
von eyescube
Hallo ich bins nochmal,
ich hab ein Problem mit einer Datei
die wichtigsten Codeteile sind:

Code: Alles auswählen

def read_config(self):
		choice, date, dest = None, None, None
		try:
			file = open(self.config_file)
			for line in file.readlines():
				if line.lower().strip().startswith("boottime"):
					choice = re.split('^boottime\s*=\s*([0-9]+)', line.lower().strip())[1]
				elif line.lower().strip().startswith("destination="):
					dest = re.split('^[dD][eE][sS][tT][iI][nN][aA][tT][iI][oO][nN]\s*=\s*(.+)\s*$', line.strip()
also in der datei steht
text
boottime=7
destination= \pfad\für\sicherung\
aber wenn ich die datei anhänge sie das so aus
\pfad\für\sicherung\/datei.tar
wie bekomm ichs hin das der slash geändert wird?

Re: replace problem

Verfasst: Donnerstag 7. April 2011, 16:11
von BlackJack
@eyescube: Zum manipulieren von Pfaden gibt es im `os.path`-Modul eine ganze Menge Funktionen. Unter anderem welche zum Normalisieren und Verbinden von Pfad-Teilen.

Re: replace problem

Verfasst: Donnerstag 7. April 2011, 16:13
von deets
Zwei Dinge:

- gibt es einen Grund, warum du nicht das Modul ConfigParser verwendest?
- wenn es schon regulaere Ausdruecke sein muessen, warum benutzt du nicht re.IGNORECASE, um deinen Ausdruck wenigestens halbwegs lesbar zu gestalten?

Re: replace problem

Verfasst: Donnerstag 7. April 2011, 16:15
von BlackJack
@deets: Schau Die mal die Zeile darüber an -- nach Grossbuchstaben zu suchen ist in dem Fall sowieso total sinnfrei. Aber das, und einiges andere, wurde dem OP schon mal gesagt…

Re: replace problem

Verfasst: Donnerstag 7. April 2011, 16:22
von snafu
Ungetestet:

Code: Alles auswählen

with open(self.config_file) as f:
    for line in f:
        name, value = line.split('=')
        if name.lower() == 'boottime':
            boottime = value
        elif name.lower() == 'destination':
            dest = os.path.join(value, 'datei.tar')

Re: replace problem

Verfasst: Donnerstag 7. April 2011, 16:29
von Rebecca
Vielleicht besser:

Code: Alles auswählen

name, value = line.split('=', 1)
:)

Re: replace problem

Verfasst: Freitag 8. April 2011, 13:57
von lunar
@snafu: ".strip()" nicht vergessen.

@deets: ConfigParser kann das Format nicht parsen:

Code: Alles auswählen

>>> fileobj = StringIO('boottime = 1\ndestination = bar')
>>> config = ConfigParser()
>>> config.readfp(fileobj)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/usr/lib/python2.7/ConfigParser.py", line 316, in readfp
    self._read(fp, filename)
  File "/usr/lib/python2.7/ConfigParser.py", line 504, in _read
    raise MissingSectionHeaderError(fpname, lineno, line)
MissingSectionHeaderError: File contains no section headers.
file: <???>, line: 1
'boottime = 1\n'
Man kann entweder die Drittbibliothek "configobj" verwenden, oder eben selbst parsen, was ziemlich trivial ist, solange es sich um einfache, einzeilige Schlüssel-Wert-Paare handelt.

Re: replace problem

Verfasst: Freitag 8. April 2011, 15:44
von deets
@lunar

Oder man fuehrt einfach eine Sektion ein,damit's der ConfigParser schluckt, und spart sich das erfinden von eckigen Raedern. Zur Not pappt man die einfach als "[global]\n" standardmaessig davor, wenn es denn auf keinen Fall Aenderungen geben darf.

Re: replace problem

Verfasst: Freitag 8. April 2011, 16:29
von lunar
@deets: Man muss es nicht übertreiben, schließlich ist das Zerlegen solcher Schlüssel-Wert-Paare reichlich trivial. Man muss sich schon ziemlich anstellen, um dafür ein eckiges Rad zu bauen. ;)

Code: Alles auswählen

def read_config(filename):
    with open(filename) as stream:
        pairs = (l.split('=', 1) for l in stream
                 if '=' in l and not l.lstrip().startswith('#'))
        return {k.strip().lower(): v.strip() for k, v in pairs}
Das Aufbereiten für ConfigParser ist da nur unwesentlich kürzer.

Re: replace problem

Verfasst: Freitag 8. April 2011, 16:53
von deets
@lunar

Ja, so fangen sie immer an, die simplen Probleme. HTML zerlegen mit regulaeren Ausdruecken "ja, ist ja nur fuer die eine Sache, und da geht's echt", CSV-Dateien parsieren "meine Daten haben keine Kommata in ihren Werten" usw.

Raketenwissenschaft sind die wenigsten Dinge. Aber fast so schwer zu erlernen wie man auf den Mond kommt ist es, bei solchen "simplen" Dinge die richtigen Entscheidungen zu treffen. Wann darf man abkuerzen, wann schiesst man sich damit in den Fuss. Wann sollte man die Randbedingungen aendern, wann muss man sie akzeptieren.

Da finde ich es schon richtig, den OP mit den korrekten Alternativen zu konfrontieren.


Und wenn ich mir

Code: Alles auswählen


# -*- coding: utf-8 -*-
from cStringIO import StringIO
from ConfigParser import ConfigParser


data = r"""
boottime=7
destination= \pfad\für\sicherung\
"""

cp = ConfigParser()
cp.readfp(StringIO("[global]\n" + data))

print cp.items("global")
im Vergleich zum OP anschaue, dann weiss ich, was ich bevorzuge ;)

Re: replace problem

Verfasst: Freitag 8. April 2011, 17:04
von lunar
@deets: Offensichtlich sind wir unterschiedlicher Ansicht darüber, was "korrekt" ist und welcher Räder man nicht neu erfinden sollte. Aangesichts der Trivialität des Problems finde ich Vergleiche mit einem HTML-Parser oder gar mit einer Reise zum Mond allerdings ziemlich übertrieben ... lass die Mücke einfach mal Mücke bleiben, ja?

Re: replace problem

Verfasst: Freitag 8. April 2011, 18:42
von snafu
Andererseits: Es ist zwar ein unschöner Würgaround, den deets da vorschlägt, jedoch muss man sich danach auch nicht mehr mit den möglichen Eventualitäten beim Parsen herumärgern. Wenn der eingebaute ConfigParser bereits so eine Funktionalität implementiert hätte, dann würde man diese ja auch nutzen und sich das selber Basteln dementsprechend lieber ersparen wollen. Leider ist die Strukturierung in dem Modul aber wohl so gemacht, dass man IMHO nicht sinnvoll irgendwo einhaken bzw neuimplementieren könnte.