replace problem

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
eyescube
User
Beiträge: 56
Registriert: Mittwoch 6. April 2011, 06:58

Donnerstag 7. April 2011, 15:39

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?
BlackJack

Donnerstag 7. April 2011, 16:11

@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.
deets

Donnerstag 7. April 2011, 16:13

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?
BlackJack

Donnerstag 7. April 2011, 16:15

@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…
Benutzeravatar
snafu
User
Beiträge: 5934
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Donnerstag 7. April 2011, 16:22

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')
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Donnerstag 7. April 2011, 16:29

Vielleicht besser:

Code: Alles auswählen

name, value = line.split('=', 1)
:)
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
lunar

Freitag 8. April 2011, 13:57

@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.
deets

Freitag 8. April 2011, 15:44

@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.
lunar

Freitag 8. April 2011, 16:29

@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.
deets

Freitag 8. April 2011, 16:53

@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 ;)
lunar

Freitag 8. April 2011, 17:04

@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?
Benutzeravatar
snafu
User
Beiträge: 5934
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Freitag 8. April 2011, 18:42

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.
Antworten