Daten aus einem in Dictionary gespeicherter Liste auslesen und in txt.file schreiben

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
CSchilling
User
Beiträge: 25
Registriert: Sonntag 4. April 2021, 09:13

Grüßt euch,

ich möchte Daten welche in einer Liste gespeichert sind, die Liste ist als Key:Value in einem Dict gespeichert, in eine .txt-file schreiben.

In diesem Dict sind insgesamt 19 Key:Value Paare enthalten. Jede Liste(Value) hat die selbe Länge. Es kann aber sein, das eine Liste gar keine Daten enthält.

Beispiel:
Ich bekomme Daten aus dem Netz (Finanzdaten), diese verarbeite ich danach. Jenachdem was ich gerade benötige, speichere ich diese dann zueghörig in einer Liste im Dict mit den passenden Key:Value Paaren.
Das Dict sieht for der Speicherung der Daten wie folgt aus:

Code: Alles auswählen

historical_data = {}
historical_data.update(UNIX_OPENTIME=[], UNIX_CLOSETIME=[], DATE=[], OPENTIME=[],
                       OPEN=[], HIGH=[], LOW=[], CLOSE=[],
                       EMA_UP=[], EMA_DOWN=[], RSI=[],
                       EMA_8=[], EMA_14=[], EMA_50=[],
                       TR=[], ATR=[],
                       STOCH_RSI=[], SMOOTH_K=[], SMOOTH_D=[])
Nun speichere ich Daten in den jeweiligen Listen. Anschließend möchte ich die Daten aus den Listen in eine .txt-Datei übertragen.
In der .txt-Datei soll das dann wie folgt aussehen.

Zeile1: Name[KEY(1)],Name[KEY(2)],...,Name[KEY(n)]
Zeile2: Daten[KEY(1)[0]],Daten[KEY(2)[0]],...,Daten[KEY(n)[0]]
Zeile3: Daten[KEY(1)[1]],Daten[KEY(2)[1]],...,Daten[KEY(n)[1]]
Zeile3: Daten[KEY(1)[k]],Daten[KEY(2)[k]],...,Daten[KEY(n)[k]]

Als Header sollen die Namen der KEY´s stehen getrennt durch ein Komma.
Und in den Zeilen darunter, die jeweiligen Daten aus den Listen, zugehörig zu den KEY´s.
Wie bereits erwähnt, kann es vorkommen, das ein KEY:Value Paar keine Daten in der Liste gespeichert hat. Dann soll diese auch nicht in der .txt-Datei gespeichert werden.
Wichtig ist, dass die Daten in der selben Reihenfolge aus der Liste übernommen werden sollen.
Mein Ansatz war nun bisher soweit gekommen, dass ich die Header in die .txt-Datei übertragen habe.
Nun steh ich etwas auf dem Schlauch, wie ich die Zeilen danach befülle.

Code: Alles auswählen

def write_to_file(*args):
    """"""

    line = ",".join(map(str, args))
    with open("data.txt", "a", encoding="utf-8") as file:
        file.write(f"{line}\n")

arg = []
for key in historical_data:
    if historical_data[key]:
        arg.append(key)

write_to_file(*arg)
Für Anregungen und Hilfen wär ich wiedermal sehr dankbar!!

Schönen Abend euch.

Chris
CSchilling
User
Beiträge: 25
Registriert: Sonntag 4. April 2021, 09:13

EDIT:

Kurz was gegessen und nochmal nachgedacht...
hab das nun wie folgt "gelöst".

Code: Alles auswählen

def write_to_file(*args):
    """"""

    line = ",".join(map(str, args))
    with open("historical_data.txt", "a", encoding="utf-8") as file:
        file.write(f"{line}\n")
        

arg = []
for key in historical_data:
	if historical_data[key]:
		arg.append(key)

write_to_file(*arg)
arg.clear()
                
for index, _ in enumerate(historical_data["UNIX_OPENTIME"], start=0):
	for key in historical_data:
		 if historical_data[key]:
                            arg.append(historical_data[key][index])
	write_to_file(*arg)
	arg.clear()
Jemand eine Idee, das etwas schlanker und effizienter zu lösen?
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Hast Du statt einer txt-Datei vielleicht eigentlich eine csv-Datei? Dann benutze das csv-Modul.
Du könntest Dir auch pandas anschauen.

Statt für jede Zeile die Datei neu zu öffnen, öffne sie einmal und schreibe alle Daten nacheinander.
Statt in jedem Schleifendurchgang zu prüfen, ob die Liste leer ist, würde man einmal ein neues Wörterbuch erzeugen, das nur gefüllte Listen enthält.
Dann steckst Du alle Listen in eine Liste und transponierst sie mit zip.

Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht eine Mischung aus Leerzeichen und Tabs.
CSchilling
User
Beiträge: 25
Registriert: Sonntag 4. April 2021, 09:13

Sirius3 hat geschrieben: Mittwoch 23. Juni 2021, 07:34 Hast Du statt einer txt-Datei vielleicht eigentlich eine csv-Datei? Dann benutze das csv-Modul.
Du könntest Dir auch pandas anschauen.

Statt für jede Zeile die Datei neu zu öffnen, öffne sie einmal und schreibe alle Daten nacheinander.
Statt in jedem Schleifendurchgang zu prüfen, ob die Liste leer ist, würde man einmal ein neues Wörterbuch erzeugen, das nur gefüllte Listen enthält.
Dann steckst Du alle Listen in eine Liste und transponierst sie mit zip.

Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht eine Mischung aus Leerzeichen und Tabs.

Hi Sirius,

die Daten lade ich von einem Server aus dem Internet. Ich kann die Daten auch in eine csv-Datei schreiben. Ob nun csv oder txt, das spielt eigentlich keine Rolle.
Deine Tipps werd ich umsetzen!
Vielen Dank :D .

Die Einrückungen sind irgendwie nur hier in dem Forum in dem Thread so raus gekommen.
In PyCharm rücke ich immer nur mit mit 4 Leerzeichen ein :roll:

Dir noch einen angenehmen Tag!
LukeNukem
User
Beiträge: 232
Registriert: Mittwoch 19. Mai 2021, 03:40

CSchilling hat geschrieben: Mittwoch 23. Juni 2021, 13:38 die Daten lade ich von einem Server aus dem Internet. Ich kann die Daten auch in eine csv-Datei schreiben. Ob nun csv oder txt, das spielt eigentlich keine Rolle.
Das Datenformat, das Du da manuell zusammenbasteln möchtest, nennt sich nun einmal CSV, unabhängig davon, ob Du es als "txt" bezeichnest und ebenso unabhängig davon, ob Du die Daten aus dem Internet lädst, aus einer Glaskugel liest, oder vom Mond gemorst bekommst. Und so einfach CSV auch auf den ersten Blick aussehen mag, kann ich Dir aus -- bisweilen sehr leidvollen und schmerzhaften -- Erfahrungen sagen, daß es etliche Tücken und Fallen hat.

In Deinem Fall fängt das schon mit der Locale an. Wenn Du Daten aus dem Internet liest, dann liegen sie Dir -- solange Du sie nicht entsprechend konvertierst -- zunächst nur als Zeichenketten vor. Das ist ein bisschen blöd, denn dann hängt der Dezimaltrenner von der Locale des Servers ab: ein Server mit einer angloamerikanischen Locale wird wahrscheinlich einen Punkt als Dezimaltrenner und ein Komma zur Zifferngruppierung benutzen, also etwa "123,456,789.0101", während ein deutscher oder russischer Server womöglich "123.456.789,0101" liefert -- und beide Notationen bezeichnen denselben Zahlenwert.

Aber jetzt willst Du diese Daten in einer Datei speichern und konkatenierst sie -- ausgerechnet -- mit dem Dezimal- oder Gruppierungstrenner der jeweiligen Locale. Dem könntest Du entgegenwirken, indem Du die Zahlen entweder in Anführungszeichen notierst ("123,456,789.0101"), auch Quoting genannt, oder die betreffenden Zeichen maskierst (123\,456\,789.0101). In beiden Fällen werden sowohl das Lesen, als auch das Schreiben ohne entsprechende Bibliotheken etwas... mühselig. Etwas einfacher könnte es sein, einen anderen Feldtrenner zu wählen, Semikola (";") sind sehr beliebt, aber auch Pipe-, At- und Hashzeichen ("|", "@", "#") habe ich schon gesehen.

Zum Glück hat Python direkt eine passende Bibliothek, die sich selbständig und transparent um dieses ganze Low-Level-Zeug kümmern kann: das Standardmodul "csv". Das hat obendrein noch ein paar andere schicke Vorteile, zum Beispiel, daß das CSV-Modul von Python ein in C geschriebenes Backend hat, das wesentlich performanter ist als ein in Python geschriebener Code. Zumal als ein räusper Code, der für jede Zeile die Datei öffnet und wieder schließt...

Wenn Du Dich nun einmal hinreißen läßt und in die Dokumentation dieses csv-Moduls schaust, was ich Dir wärmstens ans Herz legen möchte, dann wirst Du schnell feststellen, daß es da sogar schon etwas gibt, das genau gemacht ist für Deinen Anwendungsfall, nämlich Dictionaries zu schreiben: den csv.DictWriter. Dem gibst Du im Konstruktor die Feldnamen mit, schreibst mit der Methode writeheader() die gewünschte Header-Zeile, und dann kannst Du Deine Daten-Dictionaries einzeln mit der Methode writerow(), oder sie alle auf einmal (oder auch chunkweise) mit der Methode writerows() in Deine Datei schreiben. Analog zum csv.DictWriter gibt es übrigens auch einen csv.DictReader zum -- Überraschung! -- Lesen solcher Dateien.

Übrigens: wenn Du häufiger mit CSV-Dateien arbeitest, könnte es sich lohnen, das in Python geschriebene Programmpaket csvkit zu installieren. Da sind eine ganze Menge sehr nützlicher Programme drin -- es muß nicht immer das arme MS Excel sein, das ohnehin die meistmißbrachte Software der Welt ist und bei größeren CSVs obendrein versagt. ;-)
CSchilling
User
Beiträge: 25
Registriert: Sonntag 4. April 2021, 09:13

@LukeNukem
wow, Danke für die ausführliche Antwort!!

mit dem csv-modul in python hab ich mich bereits nach Sirius seinem Beitrag beschäftigt und schreibe damit nun die Daten als csv in eine .txt-Datei.
Die erhaltenen Daten aus dem Netz, werden erstmal von mir, vor der endgültigen Speicherung in einer .txt-Datei, weiterverarbeitet. Somit hatte ich auch bereits das Vergnügen mit den von dir zu Beginn erwähnten Tücken :-P.

Besten Dank an dieser Stelle und eine schöne Restwoche.

Grüße, Chris
Antworten