kann man das smarter/eleganter lösen ?

  • moinsen,

    ich werde hier von zeit zu zeit ein paar codes posten - warum dann dafür einen neuen thread eröffnen ...

    1. code-beispiel:


    ich habe eine csv-datei, die 30 einträge hat. mehr sollen es auch nicht werden. täglich kommt EIN neuer eintrag (neue zeile am ende der datei) hinzu, weswegen die zweite zeile (in der ersten zeile befinden sich die spaltenüberschriften) gelöscht werden muss. mein code:

    Code
    file = 'E:\\APPDATA\\Atom\\Python\\Scripts\\test.csv'
    entry = "\nneu1,neu2"
    with open(file,'a+') as csvfile:
        csvfile.write(entry)
        csvfile.seek(0)
        lines = csvfile.readlines()
        del lines[1]
    with open(file, "w") as csvfile:
        for l in lines:
            csvfile.write(l)

    merci im voraus

    so long


    EDIT: in diesem thread werde ich mehrere code-beispiele posten

    --- wer lesen kann, ist klar im Vorteil ---

    --- Freude entsteht aus Mangel an Information ---

    --- Scheiße ist, wenn der Furz etwas wiegt ---


    Edited 2 times, last by Perlchamp: schreibfehler ().

  • hi tell,

    es hat schon seinen grund, warum ich a+ als modus gewählt habe ;)

    es geht darum, einen verlauf anzuzeigen (grafisch), wobei die entries von der ersten zeile an abgearbeitet werden. die erste zeile ist der älteste eintrag, die letzte zeile der neuste ... für ein diagramm mit der xachse als zeitachse => links alt, rechts neu

    --- wer lesen kann, ist klar im Vorteil ---

    --- Freude entsteht aus Mangel an Information ---

    --- Scheiße ist, wenn der Furz etwas wiegt ---


  • Ok, und was ist damit:

    Code
    file = 'test.csv'
    entry = "neu1,neu2\n"
    with open(file,'r+') as csvfile:
        lines = csvfile.readlines()
        csvfile.seek(0)
        csvfile.write( lines[0] )
        for l in lines[2:]:
            csvfile.write(l)
        csvfile.write( entry )
  • hi tell,

    danke zuerst einmal für deine zeit !

    klar, funktionieren würde es ... ich möchte auch nicht unhöflich sein. smart ist anders, odda ?

    --- wer lesen kann, ist klar im Vorteil ---

    --- Freude entsteht aus Mangel an Information ---

    --- Scheiße ist, wenn der Furz etwas wiegt ---


  • Hallo,


    "smart" ist auch nicht wirklich einfach, weil der Ansatz die Länge der Datei auf 30 Einträge zu beschränken, sagen wir mal "unüblich" ist und deshalb ein "smarte Lösung" schwierig ist. Da du ja nicht gleichzeitig in die selbe Datei schreiben kannst, aus der du liest (bzw. das Seiteneffekte hat), musst du ja erst alles lesen und dann schreiben.


    Zum Arbeiten mit CSV-Dateien nimmt man auch normalerweise das CSV-Modul.

    Der folgende Code macht aus:

    Code
    x;y
    a;1
    b;2
    c;3
    d;4
    e;5


    die CSV-Datei:

    Code
    x;y
    b;2
    c;3
    d;4
    e;5
    f;6

    Code:

    Das ist zwar deutlich länger, aber dafür auch deutlich expliziter und man muss nicht mit `seek` und Slicing rum fummeln.


    Ein alternativer Weg wäre, das `deque` Objekt als Hauptdatenspeicher zu nutzen, diese via `pickle` zu speichern und daraus bei Bedarf eine CSV Datei bauen. Oder besser eine DB wie SQLite nehmen und für die grafische Darstellung nur die letzten 30 Werte nehmen. Oder RRD nehmen, was out of the box mit einem Ringpuffer arbeitet und nur die letzten X Werte speichert.


    Gruß, noisefloor

  • Mein Vorschlag zur ursprünglichen Frage, ungeachtet der Frage, ob sqlite oder das csv-Modul die bessere Lösung wären:

    Code
    file = 'test.csv'
    entry = "neu1,neu2\n"
    with open(file,'r+') as csvfile:
        lines = csvfile.readlines()
        del lines[1]
        lines.append(entry)
        csvfile.seek(0)
        csvfile.writelines(lines)
        csvfile.truncate()
  • ich habe noch eine frage:

    wenn ich als string 12.564,89 UMD habe, ich aber nun 12564.89 haben möchte, gibt's dafür eine elegantere lösung als :

    Code
    pallstr = "12.564,89 UMD"
    # manipulation
    pallstr = pallstr[:-4]
    pallstr = pallstr.replace(".", "")
    pallstr = pallstr.replace(",", ".")

    ein merci im voraus.

    --- wer lesen kann, ist klar im Vorteil ---

    --- Freude entsteht aus Mangel an Information ---

    --- Scheiße ist, wenn der Furz etwas wiegt ---


  • moinsen,

    die daten werden später sowieso als json-string weiterverarbeitet, insofern hatte ich darauf kein augenmerk gelegt. dennoch vielen dank für die anregung :) aaber:

    da ich alles in eine sqlite-db einpflege kann ich dort ja nach belieben (?) diesen wert als zahl interpretieren (lassen) ?

    à propos sqlite:

    ist das in buster standardmäßig installiert? ich finde nämlich keinen ordner ~/.sqliterc

    --- wer lesen kann, ist klar im Vorteil ---

    --- Freude entsteht aus Mangel an Information ---

    --- Scheiße ist, wenn der Furz etwas wiegt ---


  • Hallo,


    Python hat immer SQLite als Modul an Bord, sofern du Python nicht selber kompiliert hast und bewusst SQLite nicht mit einkompiliert hast. SQLite muss alleine _nicht_ auf dem System sein. Ist aber auch in der Python Doku erklärt.


    SQLite kennt verschiedene Datentypen, wie auch Programmiersprachen. `12.564,89 UMD`kannst du auch in SQLite nur als String speichern.


    Quote

    insofern hatte ich darauf kein augenmerk gelegt

    Grundsätzlich gilt: so früh wie möglich und so lange wie mögliche mit Datentypen arbeiten, die Sinn machen. Bei Währung also z.B. so lange wie möglich mit Float oder Decimal und erst bei der Ausgabe konvertieren. Oder ein Python Modul nutzen, dass Währungsobjekte bereit stellt (keine Ahnung, ob es sowas gibt).


    Gruß, noisefloor

  • ich habe noch eine frage:

    wenn ich als string 12.564,89 UMD habe, ich aber nun 12564.89 haben möchte, gibt's dafür eine elegantere lösung als :

    ein merci im voraus.

    Hallo,

    wenn du wirklich die passende locale mit Punkt als tausender Trennzeichen und komma als Dezimaltrenner im OS hast (was ich jetzt erst mal bezweifel) sollte folgendes klappen:

    Code
    Import locale
    s = "12.564,89 UMD"
    locale.setlocale(locale.LC_ALL,'')
    locale.atof(s[:s.find(" UMD")])
  • locale.atof(s[:s.find(" UMD")]

    fehlt die abschliessende klammer ) ?

    ich werd's mal versuchen, danke !

    Code
    locale.atof(s[:s.find(" UMD")])
    File "C:\Program Files\Python37\lib\locale.py", line 326, in atof
    return func(delocalize(string))

    --- wer lesen kann, ist klar im Vorteil ---

    --- Freude entsteht aus Mangel an Information ---

    --- Scheiße ist, wenn der Furz etwas wiegt ---


    Edited once, last by Perlchamp ().

  • fehlt die abschliessende klammer ) ?

    ich werd's mal versuchen, danke !

    Nicht nur die Klammer sondern auch die Zeile um die locale zu laden. Habs oben angepasst.

    Wenn du de_DE.UTF8 hast, sollte es klappen. Bei mir geht's.

    Du kannst dir danach mit locale.localeconv() auch anzeigen lassen welches Trennzeichen wo verwendet wird.


    //Edit: Tippfehler

  • ja, super, hat geklappt :) , dann bin ich mal so frei :

    --- wer lesen kann, ist klar im Vorteil ---

    --- Freude entsteht aus Mangel an Information ---

    --- Scheiße ist, wenn der Furz etwas wiegt ---


    Edited 3 times, last by Perlchamp ().

  • ja, wäre mit sicherheit auch machbar. wenn ich zeit habe, werde ich mich aber trotzdem mal drum kümmern - die alten kenntnisse wieder auffrischen ;)

    --- wer lesen kann, ist klar im Vorteil ---

    --- Freude entsteht aus Mangel an Information ---

    --- Scheiße ist, wenn der Furz etwas wiegt ---


  • @EL:

    wenn ich das script über ssh ausführe funktioniert es nicht :

    Code
    dirk@raspberrypi:~ $ python3 /home/dirk/Scripte/metalcharts.py
    Traceback (most recent call last):
      File "/home/dirk/Scripte/metalcharts.py", line 23, in <module>
        gpreis = float(locale.atof(gold[:-2]))
      File "/usr/lib/python3.7/locale.py", line 326, in atof
        return func(delocalize(string))
    ValueError: could not convert string to float: '1.566,89'

    wenn ich es über VNCviewer (von realVNC) über das terminalfenster ausführe, klappt's :

    Code
    dirk@raspberrypi:~/Scripte $ python3 metalcharts.py

    ich habe windows10 x64 rechner. habe dort auch bereits unter windows-einstellungen => zeit und sprache => region => zusätzliche datums-, uhrzeit- und ländereinstellungen ändern => region => verwaltung => gebietsschema ändern => beta: unicode utf-8 für die unterstützung weltweiter sprachen (den haken gesetzt). hat sich dennoch nichts geändert. über ssh geht es nicht. hast du vielleicht noch einen tipp ?

    ich meine, ich lass es ja über den rpi laufen, auf dem es (direkt) funktioniert, ist aber doch ein wermutstropfen :(


    ein merci im voraus

    so long

    --- wer lesen kann, ist klar im Vorteil ---

    --- Freude entsteht aus Mangel an Information ---

    --- Scheiße ist, wenn der Furz etwas wiegt ---