Variablen in externer Datei speichern und abrufen.

Spedex

Ensign
Registriert
Jan. 2019
Beiträge
146
Programmiersprache: Python

Hey, ich würde gerne in einem Programm Strings, Zahlen und Listen speichern und wieder abrufen.
Zum Start des Programmes soll erstmal einer Variable mit dem Namen Punkte den Wert 9999 (Zahl) zugewiesen werden.
Dabei habe ich folgenden Aufbau verwendet.
Python:
varstemp = open("saves_donotdelete", "r")
punkte = varstemp.readlines()
punkte = punkte[1]
print ("Aktuell hast du " + str(punkte)  + " Punkte")

Die Datei saves_donotdelete hat folgenden Inhalt:
Code:
Punkte
9999

Dabei erhalte ich jedoch folgende Ausgabe in der Kommandozeile:
Code:
Aktuell hast du 9999
 Punkte

Nach der Zahl wird automatisch ein Absatz geschrieben.
Klar könnte ich den Code jetzt wie folgt ändern:
Python:
varstemp = open("saves_donotdelete", "r")
punkte = varstemp.readlines()
punkte = punkte[1]
print ("Aktuell hast du folgende Anzahl an Punkten " + str(punkte))

Jedoch schätze ich, dass das so spätestens beim Einlesen von Listen, Probleme bereiten wird.

Könnt ihr mir da weiterhelfen?
Im Internet wird vor allem eine Benutzung von for-Schleifen verwendet, was ich jedoch in meinem Code gerne vermeiden würde.
Ich nutze primär lieber while-Schleifen und außerdem habe ich schon so viele Schleifen, was dann zu Schleifen in Scheifen in Schleifen (etc.) führen würde:
Python:
while Bedingung:
    while Bedingung:
        while Unübersichtlich == True:
            Chaos
Ergänzung ()

Python:
punkte = punkte[1]
# Hier wird auf Zeile 2 zugegriffen (Versatz von 1)
# Die ursprüngliche Zeile 1 in saves_donotdelete dient nur als Anmerkung für mich
 
Zuletzt bearbeitet:
Das wird wohl daran liegen, dass hinter der 9999 noch ein newline Symbol ist, also ein "\n".
Das müsstest du entfernen :)
 
Wie wichtig ist das Format der externen Datei?
Mit xml oder json bist Du pauschal besser beraten. Die sind standardisiert und es gibt fertige Zugriffsroutinen.
 
  • Gefällt mir
Reaktionen: BeBur
RalphS schrieb:
Wie wichtig ist das Format der externen Datei?
Mit xml oder json bist Du pauschal besser beraten. Die sind standardisiert und es gibt fertige Zugriffsroutinen.
Aktuell hat die Datei keine Endung. Was für eine Endung es hat ist mir ziemlich egal, allerdings denke ich mal braucht man bei .xml oder .json eine gewisse Syntex, welche ich nicht beherrsche.
Ergänzung ()

davisx2 schrieb:
Das wird wohl daran liegen, dass hinter der 9999 noch ein newline Symbol ist, also ein "\n".
Das müsstest du entfernen :)
1570467072837.png

Es folgt eine leere Zeile. Es die für das \n verantwortlich? Durch das Speichern wird sie automatisch hinzugefügt. Alleridngs wird es ja sowieso leere Zeilen in der Datei geben.
 
Spedex schrieb:
Anhang anzeigen 828563
Es folgt eine leere Zeile. Es die für das \n verantwortlich? Durch das Speichern wird sie automatisch hinzugefügt. Alleridngs wird es ja sowieso leere Zeilen in der Datei geben.

Genau. Eher ist das \n für die Leerzeile verantwortlich, aber das tut gerade nichts zur Sache :p
Was du in punkte[1] bekommst ist nämlich nicht "9999", sondern "9999\n".
 
davisx2 schrieb:
Genau. Eher ist das \n für die Leerzeile verantwortlich, aber das tut gerade nichts zur Sache :p
Was du in punkte[1] bekommst ist nämlich nicht "9999", sondern "9999\n".
Und wie kann ich das vermeiden. Ich sehe ja kein, im Code eingebettetes, \n?
 
In dem du das letzte Zeichen abschneidest, zb mit punkte[1][:-1].
Das gibt dir den String punkte[1] ohne die letzte Stelle zurück.
Da an der letzten Stelle das \n steht, entfernst du damit die neue Zeile.
 
Spedex schrieb:
Python:
varstemp = open("saves_donotdelete", "r")
punkte = varstemp.readlines()
punkte = punkte[1]
print ("Aktuell hast du " + str(punkte) + " Punkte")

replace('\n', '')

Spedex schrieb:
Python:
varstemp = open("saves_donotdelete", "r")
punkte = varstemp.readlines()
punkte = punkte.replace('\n', '')
punkte = punkte[1]
print ("Aktuell hast du " + str(punkte) + " Punkte")


teste das mal
 
.strip sollte da helfen, oder wie von davisx2 den range-operator.

\n ist eben ein non-printable whitespace, daher siehst du das auch nirgends (außer du siehst dir direkt den Speicher an 😉)
 
Kann man denn in python nicht auch optional typisieren?
Meines Erachtens relativ sauber wäre auch
Code:
print ("Aktuell hast du " + str(int(punkte))  + " Punkte")
Schöner wäre es natürlich, wenn punkte schon beim Einlesen auf eine Zahl typisiert wäre.
 
Alles klar. Ich werde es mal ausprobieren und schauen, ob es sich auch auf Listen übertragen lässt. Sollte ich nicht weiterkommen, werde ich mich nochmal meldem. Ich denke mal, beim schreiben von Informationen kommen erst die richtigen Probleme.
Ergänzung ()

Nevermind.
Fokusiere mich derzeit erstmal auf Zahlen.
Dabei wollte ich eigentlich das gleiche machen, wie ich es eben schon gemacht habe.
Dabei kam jedoch folgende Meldung:
Code:
Traceback (most recent call last):
  File "xxx.py", line 24, in <module>
    abbaufaktor = varstemp.readlines()[4][:-1]
IndexError: list index out of range


------------------
(program exited with code: 1)

Drücken Sie eine beliebige Taste . . .

Die Datei hat dabei folgenden Inhalt:
Code:
Punkte
9999

abbaufaktor
1

Warum gibt es hierbei schon Probleme? Ist doch eigentlich alles gleich wie vorher?
 
Zuletzt bearbeitet:
Rufst du das readlines() nach dem Code auf, den du uns vorher gezeigt hast?
Sodass du im Endeffekt 2 mal readlines dastehen hast?
 
Ja. Ich folgendes steht oben:
Python:
varstemp = open("saves_donotdelete", "r")
Dann wollte ich einfach varstemp.readlines() einer Variable zuweisen, die ich dann somit abrufe.
Ergänzung ()

Python:
varstemp = open("saves_donotdelete", "r")
punkte = varstemp.readlines()[1][:-1]

print ("Aktuell hast du " + str(punkte)  + " Punkte")

abbaufaktor = varstemp.readlines()[4][:-1]
# Nicht relevante Zeilen wurden entfernt
 
Ok, hier kann ich dir nicht erklären wieso es nicht funktioniert (bin nicht gerade der Python Experte), aber 2 mal readlines funktioniert soweit ich weiß nicht.
Entweder schließt und öffnest du die Datei vor dem Lesen, oder was sinnvoller ist, du speicherst das varstemp.readlines in einer variable, von der du dann deine werte rausziehst.
Python:
punkte = varstemp.readlines()[1][:-1]
#wird zu
variablen = varstemp.readlines()
punkte = variablen[1][:-1]
#und die anderen sachen auch aus variablen auslesen
 
JSON und XML musst dir nur anschauen. Das ist sehr sehr einfach.

JSON:
{
    "Punkte":9999,

    "abbaufaktor": 1
}

XML:
<punkte>9999</punkte>
<abbaufaktor>1</abbaufaktor>
 
Hey, das Abrufen von Zahlen hat nun wunderbar funktioniert.
Dabei ergab sich folgender wunderschöner Aufbau:
Python:
varxy = int(savedatei[4][:-1])
varxy = int(savedatei[7][:-1])
varxy = int(savedatei[10][:-1])
varxy = int(savedatei[13][:-1])
varxy = int(savedatei[16][:-1])
varxy = int(savedatei[19][:-1])
varxy = int(savedatei[22][:-1])
varxy = int(savedatei[25][:-1])
# varxy haben eigentlich anderen Namen

Jetzt möchte ich jedoch eine Liste abrufen. Dazu habe ich eine eigene Datei erstellt, welchen Folgenden Inhalt hat:
Code:
["Teil1", "Teil2"]
Auch bei der Ausgabe erhaltet man eine Liste:
Code:
["Teil1", "Teil2"]
Möchte ich jetzt jedoch einen String anfügen, mit folgendem Code:
Python:
saveinventar = invtemp.readlines()

absatz = "\n"
#Wird für .join Funktion benötigt
inventar = saveinventar
inventar.append("Test123")
if len(inventar) < 20:
    print ("Du hast aktuell folgende Elemente im Inventar:")
    print (absatz.join(inventar))
Erscheint folgende Ausgabe:
Code:
Du hast aktuell folgende Elemente im Inventar:
["Teil1", "Teil2"]

Test123
Das eigentlich große Problem: Die Liste steht so da wie sie in der Datei steht. mit .join(inventar) sollte es eigentlich eine Auflistung geben. Ohne Klammern und nach jedem Eintrag erfolgt eine neue Zeile.
Das ist hier nicht der Fall. Sprich "Test123" wird nicht drangehangen + Es steht falsch da.

Ich weiß nicht @davisx2 ob dir dass nicht zu Python-spezifisch ist, aber ich wäre über jede Hilfe dankbar.
Ergänzung ()

Code:
Traceback (most recent call last):
  File "xxx.py", line 21, in <module>
    inventar.append("Test123")
AttributeError: 'str' object has no attribute 'append'


------------------
(program exited with code: 1)

Drücken Sie eine beliebige Taste . . .
Nevermind. Es ist ein String.
Python:
inventar = saveinventar[0]
#anstatt
inventar = saveinventar
Ergänzung ()

Hab im Internet folgendes gefunden:
Python:
string.split("delimiter")
Hierbei wird:
"Geeks for Geeks"
zu
['Geeks', 'for', 'Geeks']
Info
Trotzdem nicht optimal. Kann man das ganze direkt als List einlesen?
 
Zuletzt bearbeitet:
Hi,
sowas baut man nicht selber - dafür benutzt man fertige Bibliotheken.
Man baut ne Klasse (die auch Unterklassen enthalten darf) und diese macht man jeweils 'serialisierbar'
Wenn du also googlest
"python serialize object"
dann findet man zB
https://docs.python.org/3/library/pickle.html
und
https://docs.python-guide.org/scenarios/serialization/

Wichtig: Früher oder später wirst du in die Situation kommen, dass du deine serialisierten Datentypen (die Klassen) verändert hast und daher alte Dateien inkompatibel werden könnten. Dh hierfür braucht man etwas wie 'class versioning' oder 'object versioning'. zB hier: https://stackoverflow.com/questions/2361140/pickled-object-versioning
Oder nach sowas suchen:
python serialization object versioning
 
kuddlmuddl schrieb:
Hi,
sowas baut man nicht selber - dafür benutzt man fertige Bibliotheken.
Man baut ne Klasse (die auch Unterklassen enthalten darf) und diese macht man jeweils 'serialisierbar'
Wenn du also googlest
"python serialize object"
dann findet man zB
https://docs.python.org/3/library/pickle.html
und
https://docs.python-guide.org/scenarios/serialization/

Wichtig: Früher oder später wirst du in die Situation kommen, dass du deine serialisierten Datentypen (die Klassen) verändert hast und daher alte Dateien inkompatibel werden könnten. Dh hierfür braucht man etwas wie 'class versioning' oder 'object versioning'. zB hier: https://stackoverflow.com/questions/2361140/pickled-object-versioning
Oder nach sowas suchen:
python serialization object versioning
Ich weiß deinen Aufwand sehr zu schätzen @kuddlmuddl, aber das ist für mein Programmier-Niveau, ein wenig zu "Overkill".
 
Du kannst JSON benutzen in diesem Fall (import json nicht vergessen).
Ich habs mit diesem tollen Code ausprobiert :D
Python:
import json

text = open("data","r")
data = json.loads(text.readlines()[0])
print(data)
data.append("new")
print(data)

Für deinen Code angepasst (hoffe ich, ist schwer ohne es testen zu können):
Python:
saveinventar = invtemp.readlines()
inventar = json.loads(saveinventar[0])
inventar.append("Test123")
if len(inventar) < 20:
    print ("Du hast aktuell folgende Elemente im Inventar:")
    print (inventar)
json.loads erwartet einen String, weswegen du bei einem readlines explizit die erste Zeile nehmen musst. Bei readline könntest du es direkt übergeben.
Wenn du das nicht benutzen möchtest, ist das split glaube ich noch die beste Lösung.
 
Zuletzt bearbeitet:
Ein Traum :D.
Funktioniert einwandfrei.
Dieses "JSON" gefällt mir. Sozuagen ein Python-Einlese-Upgrade

Jetzt geht es dann zum Schreiben von Informationen.
Ergänzung ()

Vielleicht wäre es schlauer, wenn ich die Zahlen auch auf JSOn aktualisiere.
@davisx2 könntest du mir vielleicht da aushelfen?
data = json.loads(text.readlines()[0]) Kann ich ja nur einmal verwenden. Ich möchte aber mehrere Werte in unterschiedlichen Zeilen abrufen.
Ergänzung ()

Wenn ich das [0] weglasse, wirft er mir sofort ein Error.
Würde es wirklich gerne verstehhe, damit ich es in Zukunft immer anwenden kann. Es ist echt praktisch ^^
 
Zuletzt bearbeitet:
Zurück
Oben