Seite 1 von 1
Strings vebinden
Verfasst: Samstag 9. November 2019, 12:36
von Peter18
Ein freundliches Hallo an alle,
ich lese Strings aus einer Konfigurationsdatei und möchte sie zu einem Sring verbinden. Das Ergebnis ist aber etwas seltsam! Was läuft da falsch??
Code: Alles auswählen
Fl = file( "Wetter.cfg", "r" )
for Z in Fl:
Z = Z.replace("\n", "")
L = Z.split("=", len(Z) )
if L[0] == "DataPath" : DatPath = L[1]
if L[0] == "Wetter" : filename1 = DatPath + L[1]
Ergebnis:
/media/USB_1G/wetter/
Wetter.csv_1G/wetter/
Warum nicht so: "/media/USB_1G/wetter/Wetter.csv"?
Grüße von der nebligen Nordsee
Peter
Re: Strings vebinden
Verfasst: Samstag 9. November 2019, 14:26
von __blackjack__
@Peter18: Das ist nicht das Ergebnis, beziehungsweise nicht alles ist sichtbar. Da scheinen nicht nur Zeilenendezeichen in der Datei zu sein ("\n"), sondern auch Wagenrückläufe ("\r"), und die hatten bei Schreibmaschinen/Druckern den Effekt das der Druckkopf an den Zeilenanfang zurück fährt, und im Terminal das der Cursor an den Zeilenanfang zurück geht. Du willst auch nicht wirklich "\n" in der gesamten Zeile ersetzen, sondern am Ende entfernen. Ich würde da einfach `strip()` verwenden und gleich alle Whitespace-Zeichen am Anfang und am Ende entfernen.
Weitere Anmerkungen zum Quelltext: Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).
Namen sollten dem Leser vermitteln was der Wert dahinter im Kontext des Programms bedeutet. `Fl`, `Z`, und `L` tun das so überhaupt nicht. Bei `DatPath` feht ein `a` und ein Unterstrich: `data_path`, und bei `filename1` hängt eine unsinnige 1 am Namen.
Dateien die man öffnet, sollte man auch wieder schliessen. Wo es geht arbeitet man am besten mit der ``with``-Anweisung. Ausserdem sollte man bei Textdateien eine explizite Kodierung angeben.
Das zweite Argument beim `split()` macht so überhaupt keinen Sinn. Das ist zum begrenzen wie oft maximal aufgeteilt werden soll, wobei `len(Z)` einen um 1 grösseren Wert liefert als überhaupt *möglich* ist, denn eine n Zeichen lange Zeichenkette kann an höchstens n-1 Stellen getrennt werden. Und an allen möglichen Stellen zu trennen ist die Voreinstellung. Allerdings möchte man das hier ja auch gar nicht, sondern das eher auf *1* beschränken, damit nur das erste "=" als Trenner dient und weitere im Wert nach dem "=" erhalten bleiben. Für den Sonderfall 1 gibt es die `partition()`-Methode.
In den beiden ``if``\s ist der Code komisch ausgerichtet und der Schleifenkörper gehört eigentlich in eine neue Zeile.
Das zweite ``if`` sollte ein ``elif`` sein, denn das erste Element kann nicht gleichzeitig die beiden Werte aus den Bedingungen enthalten.
Der Code geht implizit von einer bestimmten Reihenfolge der Werte in der Datei aus, und wohl auch das die beiden Schlüssel genau einmal vorkommen. Das ist eine potentielle Fehlerquelle.
Pfade setzt man nicht mit ``+`` zusammen, sondern mit `pathlib`.
Re: Strings vebinden
Verfasst: Samstag 9. November 2019, 14:36
von __blackjack__
Upsi, jetzt bin ich einfach so über das `file` hinweg gegangen: Das war in Python 2 falsch, dafür ist die `open()`-Funktion da. Mittlerweile ist aber Python 2 insgesamt falsch. Und in Python 3 gibt es `file` auch gar nicht mehr. Man sollte keine neuen Sachen mehr in Python 2 schreiben. Das ist in zwei Monaten mausetot und das ist seit *Jahren* bekannt.
Ungetestet:
Code: Alles auswählen
#!/usr/bin/env python3
from pathlib import Path
def main():
data_path = None
filename = None
with open("Wetter.cfg", "r", encoding="ascii") as lines:
for line in lines:
key, equals, value = line.strip().partition("=")
if equals == "=":
if key == "DataPath":
data_path = Path(value)
elif key == "Wetter":
filename = Path(value)
if not (data_path and filename):
print("Fehler")
else:
full_path = data_path / filename
...
if __name__ == "__main__":
main()
Re: Strings vebinden
Verfasst: Samstag 9. November 2019, 16:18
von Peter18
Hallo __blackjack__,
Dank Dir für die ausführliche Antwort! Hätt ich eigntlich auch selber drauf kommen können, aber Lnux ist noch etwas ungewohnt. Die Datei ist unter Windos entstanden.
Das, was ich oben an Quelltext gezeigt habe ist nur ein Auszug aus einem Testprogramm und die Variablen sollen mir etwas sagen. Mit diesem Programm teste ich ein paar Funktionen. Dass "strip" auch CRLF entfernt habe ich der Beschreibung nicht entnehmen können. Den split-Parameter habe ich anscheinend in der Beschreibung nicht richtig zur Kenntnis genommen oder mit einem anderen verwechselt.
Mit Python bin ich noch am Anfang. Daher ist manches "quick and dirty". "elif" bietet sich in diesem Fall nicht an, da es zu einer sehr unübersichtlichen Einrückung führen würde, aber "case" habe ich für Python noch nicht gefunden. In Pascal geht "case" mit Strings nicht, daher dieser Aufbau.
Nochmals Dank für die ausfhrliche Antwort! Manchmal erhält man nur ein Wort oder einen Satz und darf dann raten.
Aber noch 2 Fragen:
- Gibt es in Python case? Für Strings?
- Wie kann ich diese Frage als gelöst markieren?
Grüße von der Nordsee
Peter
Re: Strings vebinden
Verfasst: Samstag 9. November 2019, 16:51
von __blackjack__
@Peter18: Durch ``elif`` ändert sich nichts an der Einrückung, nur daran was dann nicht mehr unnötigerweise ausgeführt werden muss.
``case`` gibt es in Python nicht. Das macht man entweder mit ``if``/``elif``/``else`` oder mit einem Wörterbuch was beispielsweise Zeichenketten auf Funktionen abbildet.
Beiträge werden hier nicht als gelöst markiert.
Re: Strings vebinden
Verfasst: Samstag 9. November 2019, 17:35
von Peter18
Hallo __blackjack__,
nochmals Dank Dir!
__blackjack__ hat geschrieben: Samstag 9. November 2019, 16:51
mit einem Wörterbuch was beispielsweise Zeichenketten auf Funktionen abbildet
gibst Du mir nen Tipp??
Grüße von der Nordsee
Peter
Re: Strings vebinden
Verfasst: Samstag 9. November 2019, 19:32
von __blackjack__
@Peter18: Alles was man an einen Namen binden kann ist in Python ein Objekt und damit ein Wert. Auch Funktionen, Module, Klassen, und Methoden beispielsweise. Also kann man sich ein Wörterbuch aufbauen in dem Werte nach denen entschieden werden soll was ausgeführt werden soll als Schlüssel verwendet werden, und Funktionen oder Methoden die dann die Arbeit zu dem Schlüssel erledigen als Werte. Man holt sich dann über den Schlüssel die Funktion/Methode und ruft die auf. Bei Deinem Codebeispiel macht das aber keinen Sinn, weil das mehr Aufwand ist als es nutzen bringt, und man müsste auch ein Objekt für den Zustand einführen das man dann den Funktionen übergeben kann.
Re: Strings vebinden
Verfasst: Sonntag 10. November 2019, 11:34
von Peter18
Hallo __blackjack__,
nochmals Dank! Das was ich oben gezeigt habe ist nur ein kleiner Teil. Vielleicht ist es auch etwas, das sich in Pascal umsetzen läst. Da gibt es zwar andere Lösungen, aber vielleicht ist diese ja eleganter und neues lernen ist immer gut!
Gibst Du mir ein Beispiel?
Grüße von der Nordsee
Peter
Re: Strings vebinden
Verfasst: Sonntag 10. November 2019, 12:09
von __blackjack__
Hm, das letzte mal an das ich mich auf Anhieb erinnern kann hier im Forum war dieses Beispiel:
viewtopic.php?f=31&t=45892&start=15#p354591
Ist etwas länger und da steckt das in der `mainloop()`-Funktion. Anstelle der Zeichenketten würde ich da lieber einen Aufzählungstyp mit `enum.Enum` nehmen.
Grundsätzlich geht so etwas auch in Pascal, allerdings alles etwas aufwändiger wegen der statischen Typisierung, und weil es zumindest im klassischen Pascal keinen Wörterbuch-Typ gibt. Den müsste man sich also selbst schreiben oder aus einer Bibliothek einbinden. Falls die Werte über die ”dispatched” wird ganze Zahlen (oder ein Aufzählungstyp allgemein) sind, kann man das in Pascal natürlich über ein Array mit Prozedurzeigern lösen.
Re: Strings vebinden
Verfasst: Sonntag 10. November 2019, 12:19
von nezzcarth
Peter18 hat geschrieben: Samstag 9. November 2019, 16:18
In Pascal geht "case" mit Strings nicht, daher dieser Aufbau.
Nebenbei: In freepascal geht case auch mit Strings. Welchen Pascal-Dialekt hast du denn im Blick?
Re: Strings vebinden
Verfasst: Sonntag 10. November 2019, 13:48
von Peter18
Hallo __blackjack__,
und wieder danke! Die Beschreibung werde ich mir ansehen.
Deine Idee mit dem Aufzählungstyp ist gut! Mit dem Index kann man dann in den Case gehen.
Ich verwende Delphi 4. In besonderen Fällen auch Lazarus.
Grüße von der sonnigen Nordsee
Peter