Textadventure PyQT Klassenobjekt in eine Datei speichern

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
MartinausWien
User
Beiträge: 15
Registriert: Dienstag 15. Dezember 2020, 00:41

Hallo Pythonleute,

hab mich gerade neu angemeldet.
vielleicht kann mir jemand weiterhelfen.

Die Frage, an der ich einfach nicht weiterkomme:
Es geht da quasi um die Spielstandsicherung, in welchem Raum man sich gerade befindet.
wie speichere ich ein Klassenobjekt in PyQt in eine Datei und lese es dann wieder aus. :cry:
ist es überhaupt möglich ein Klassenobjekt in PyQt einfach mit pickle.dump abzuspeichern?
mit Tkinter "löste" sich dies über pickledump aber in PyQt bekomme ich da Process finished with exit code -1073740791 (0xC0000409)

def save(self):
with open("objekt.bin", 'wb') as file:
pickle.dump(raumjetzt, file)
file.close()

wie oben hat es in Tkinter schon funktioniert.
Die Einrückungen passen nur jetzt in der Vorschau nicht mehr.

raumjetzt ist ein Objekt in einer Klasse Room:
class Room:
def _init__(self, raumname, beschreibung):

self.raumname = raumname
self.beschreibung = beschreibung

ändere ich z.B bei pickle.dump (raumjetzt.raumname, file) gibt es keine Fehlermeldung, aber dann speichere ich im objekt.bin nur den Raumnamen.

Kann mir da jemand vielleicht einen Tipp geben woran es liegen könnte?
liegt es vielleicht an den Klassen? habe: und darin noch die Klasse Room: erstellt, für die Räume im Textadventure
class EmptyWindow(QMainWindow):
def __init__(self):
super().__init__()
Benutzeravatar
__blackjack__
User
Beiträge: 13533
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@MartinausWien: Ob man (alle) Qt-Objekte picklen kann weiss ich nicht, aber Objekte der gezeigten `Room`-Klasse lassen sich picklen, ganz egal welches GUI-Rahmenwerk man verwendet. Allerdings ist das so ja auch nicht der Code den Du da tatsächlich ausführst, denn beim `Room._init__()` fehlt ein Unterstrich. Wer weiss was da im tatsächlichen Code noch anders ist.

Zeig mal ein minimales, lauffähiges Beispiel, welches das Problem aufzeigt.

Was ansonsten am Code noch auffällt ist das `save()` auf `raumjetzt` einfach so zugreifen kann als wäre das eine globale Variable‽ Funktionen und Methoden bekommen alles was sie ausser Konstanten brauchen als Argument(e) übergeben. Man verwendet keine globalen Variablen.

Wenn man ``with`` verwendet, braucht man bei der Datei keinen `close()`-Aufruf. Genau das macht das ``with`` ja.

Entscheide Dich für Deutsch oder Englisch. Am besten Englisch. `Room.description` oder `Raum.beschreibung`. Beim `raumname` ist das `raum` überflüssig, weil das durch den Kontext des `Room`-Objektes ja schon deutlich wird was das für ein Name ist.

Für Quelltext gibt es hier im Forum code-Tags damit die Einrückung im Beitrag erhalten bleibt. Im vollständigen Beitragseditor kann man die über die </>-Schaltfläche in den Beitrag einfügen.

Code: Alles auswählen

- (void)countSheep {
    unsigned int sheep = 0;
    while ( ! [self isAsleep]) { ++sheep; }
}
MartinausWien
User
Beiträge: 15
Registriert: Dienstag 15. Dezember 2020, 00:41

Hallo __blackjack__,
danke für deine rasche Anwort.
Danke für die Tipps. Das hilft mir schon mal weiter.
ad. Room.__init__() habe ich im Code eh zwei Unterstriche.
ad. with danke, hab ich schon vermuted, das close() dann überflüssig ist. hab zuvor Schreibweise file = open etc.... benutzt.
ad. Code-Tags Ist mein erster Foreneintrag, muss mich da erst zurechtfinden, werde die code-Tags verwenden und ein Beispiel zeigen.
ad. Sprache, macht Sinn, werde bei Englisch bleiben.

Das mit: "Was ansonsten am Code noch auffällt ist das `save()` auf `raumjetzt` einfach so zugreifen kann als wäre das eine globale Variable‽", werde ich mir ansehen.
Es gibt tatsächlich im Code auch eine globale Variable, vielleicht führt das zur Lösung. aber wie gesagt ich werde in Kürze den Code posten, ...
MartinausWien
User
Beiträge: 15
Registriert: Dienstag 15. Dezember 2020, 00:41

Hier der Code, bzw. das Gerüst, wo es hingehen soll.
Bitte gleich um etwas Nachsicht, da ich mich erst seit ein paar Wochen mit Python beschäftige und noch gänzlicher Anfänger bin.
PyQT ist auch ganz neu: und da bringen mich die Klassen zum grübeln.

Wie gesagt, das Problem liegt in der Definition save(self), mit raumjetzt.
ohne Auskommentierung, klappt der pickledump mit raumjetzt nicht und es kommt die Fehlermeldung.
Mit raumjetzt.raumname geht es aber, ich kann dann ja scheinbar auch auf raumjetzt zugreifen?. :?

Code: Alles auswählen

# Basis Window in PyQt
# Module importieren

import os
import pickle
import sys

from PyQt5.QtCore import QSize, Qt, QFile, QDataStream
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QTextEdit, QFrame, QScrollBar, \
    QScrollArea, QSlider, QAbstractSlider, QPushButton, QLineEdit, QListWidget, QMessageBox, \
    QVBoxLayout, QHBoxLayout, QMainWindow, QAction


class EmptyWindow(QMainWindow):
    def __init__(self):
        super().__init__() 

        self.initialize()

    # Button Funktionen bei clicked/
    # Weiterleitung an Funktion def ausgang
    # Funktion bei Auswahl Neustart im Menu

    #def neustart():
    #    os.execl(sys.executable, sys.executable, *sys.argv)




    def load(self):


        a = open('file.txt', 'r')
        entries = [e.strip() for e in a.readlines()]
        self.list.clear()
        self.list.insertItems(0, entries)
        a.close()

    def save(self):
        with open("file.txt", "w") as a:
           a.write('\n'.join(self.list.item(i).text() for i in range(self.list.count())))

        #with open("objekt.bin", 'wb') as file:
        #    pickle.dump(raumjetzt, file)




    def norden(self):
        string = "norden"
        self.ausgang(string)

    def osten(self):
        string = "osten"
        self.ausgang(string)

    def westen(self):
        string = "westen"
        self.ausgang(string)

    def suden(self):
        string = "süden"
        self.ausgang(string)

    def ausgang(self, Eingabe):
        y = raumjetzt.exits.get(Eingabe)
        if y:
            self.raum_enter(y)
        else:
            self.textfeld.append("\nDa geht es leider nicht lang.\n")

    def nehmen(self):
        self.eingabe1.clear()
        self.eingabe1.insert("Nimm")

    def schauen(self):
        self.eingabe1.clear()
        self.eingabe1.insert("Schaue")

    def benutzen(self):
        self.eingabe1.clear()
        self.eingabe1.insert("Benutze")

    def enterpress(self):
        self.textfeld.append(self.eingabe1.text())

    def itemclicked(self, item):
        self.eingabe2.clear()
        self.eingabe2.insert(item.text())
        if item.text() == 'Stein':
            print('gute Wahl')
        # self.eingabebestätigung.clicked.connect(self.bestaetige)

    def test(self):
        print('HI')

    def raum_enter(self, x):


        global raumjetzt
        raumjetzt = x

        self.raum_beschreibung()

    def raum_beschreibung(self):
        self.textfeld.append(raumjetzt.raumname)
        self.textfeld.append(raumjetzt.beschreibung)

    # Window Creator
    def initialize(self):




        # FensterGeometry MainWindow wird erstellt
        self.setGeometry(200, 40, 700, 700)
        self.setWindowTitle('Escape from Lockdown')
        # Subwidgetfenster(QWidget) wird erstellt
        self.subwidget = QWidget(self)
        self.setCentralWidget(self.subwidget)
        # Menubar wird erstellt
        self.menubar = self.menuBar()
        file_menu = self.menubar.addMenu('File')
        self.open_action = file_menu.addAction('Save', self.save)
        self.open_action = file_menu.addAction('Load', self.load)
        # Widgets (Textfelder, Buttons etc.) werden erstellt
        self.textfeld = QTextEdit(self)  # erstelle Textfeld
        self.textfeld.setFontPointSize(12)
        self.textfeld.setReadOnly(True)

        self.eingabe1 = QLineEdit(self)
        self.eingabe1.returnPressed.connect(self.enterpress)

        self.eingabe2 = QLineEdit(self)
        self.eingabe2.returnPressed.connect(self.enterpress)

        self.eingabe3 = QLineEdit(self)
        self.eingabe3.returnPressed.connect(self.enterpress)

        self.label = QLabel('mit', self)

        self.eingabe = QPushButton('Eingabe/Aktion', self)
        self.eingabe.clicked.connect(self.dieeingabe)

        self.buttonnord = QPushButton(self)
        self.buttonnord.setText('Norden')
        self.buttonnord.setStyleSheet("color: red")
        self.buttonnord.clicked.connect(self.norden)

        self.buttonwest = QPushButton(self)
        self.buttonwest.setText('Westen')
        self.buttonwest.clicked.connect(self.westen)

        self.buttonost = QPushButton(self)
        self.buttonost.setText('Osten')
        self.buttonost.clicked.connect(self.osten)

        self.buttonsud = QPushButton(self)
        self.buttonsud.setText('Süden')
        self.buttonsud.clicked.connect(self.suden)

        self.labelleer = QLabel('', self)

        self.nimm = QPushButton('Nimm', self)
        self.nimm.clicked.connect(self.nehmen)

        self.schaue = QPushButton('Schaue', self)
        self.schaue.clicked.connect(self.schauen)

        self.benutze = QPushButton('Benutze', self)
        self.benutze.clicked.connect(self.benutzen)

        self.list = QListWidget(self)
        self.list.addItem('Schwert')
        self.list.addItem('Stein')
        self.list.itemClicked.connect(self.itemclicked)

        # Layout wird erstellt und subwidget übergeben
        layout = QVBoxLayout()
        self.subwidget.setLayout(layout)
        layout.addWidget(self.textfeld)
        layout.addWidget(self.eingabe1)
        layout.addWidget(self.eingabe2)
        layout.addWidget(self.label)
        layout.addWidget(self.eingabe3)
        layout.addWidget(self.eingabe)
        layout.addWidget(self.buttonnord)
        sublayout = QHBoxLayout()
        layout.addLayout(sublayout)
        sublayout.addWidget(self.buttonwest)
        sublayout.addWidget(self.buttonost)
        layout.addWidget(self.buttonsud)
        layout.addWidget(self.labelleer)
        layout.addWidget(self.schaue)
        layout.addWidget(self.nimm)
        layout.addWidget(self.benutze)
        layout.addWidget(self.list)

        # Raumobjekte werden erstellt
        # def rooms(self):
        class Room:

          def __init__(self, raumname, beschreibung):

                   self.raumname = raumname
                   self.beschreibung = beschreibung
                   self.exits = {}

        self.wohnzimmer = Room("\nWohnzimmer:\n",
                               "Du bist im Wohnzimmer.\n"
                               "In der Mitte des Raumes steht deine bequeme 'Lockdowncouch'.\n"
                               "Im Osten ist eine Türe. Sie steht offen.\n")

        self.gang = Room("\nGang:\n",
                         "Du bist auf einem Gang.\n"
                         "Im Westen führt die Türe ins Wohnzimmer.\n"
                         "Im Süden geht es ins Schlafzimmer.\n"
                         "Im Osten ist die Eingangstüre, sie ist versperrt\n")

        self.schlafzimmer = Room("\nSchlafzimmer:\n",
                                 "Du bist im Schlafzimmer.\n"
                                 "Hier steht ein Bett.\n"
                                 "Irgendetwas liegt auf dem Bett.\n"
                                 "Im Norden geht es zu einem Gang.\n")

        # Richtungen
        #richtungen = ("norden", "osten", "süden", "westen")

        # Exits
        self.wohnzimmer.exits["osten"] = self.gang
        self.gang.exits["westen"] = self.wohnzimmer
        self.gang.exits["süden"] = self.schlafzimmer
        self.schlafzimmer.exits["norden"] = self.gang

        
        self.raum_enter(self.wohnzimmer)

    # Story of the game...
    def dieeingabe(self):

        if raumjetzt.raumname == self.wohnzimmer.raumname:

            if self.eingabe1.text() == "Schaue":
                self.textfeld.append('Du siehst nichts Auffallendes.')



# run programm

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = EmptyWindow()
    window.show()
    sys.exit(app.exec_())



Sirius3
User
Beiträge: 18051
Registriert: Sonntag 21. Oktober 2012, 17:20

Variablennamen werden generell komplett klein geschrieben. Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht mal 2 und mal 9.
Klassendefinitionen gehören auf oberste Ebene, nicht in einer Methode einer Klasse.
Warum ist raumjetzt eine globale Variable?
Warum verwendest Du beim Schreiben `with`, beim Lesen aber nicht?
`\n` ist ein Zeile-Ende-Zeichen, und kein Zeile-Trenn-Zeichen. Da fehlt zum Schluß noch ein \n.
Das readlines kann ersatzlos weg, weil ein File-Objekt schon ein Iterator über die Zeilen ist.
Die Räume solltest Du in einem Wörterbuch gespeichert werden, dann kannst Du einfach den Raum-Namen speichern und hast keine Probleme.
MartinausWien
User
Beiträge: 15
Registriert: Dienstag 15. Dezember 2020, 00:41

hallo,
Vielen Dank fürs Feedback Sirius3,

da ist gleich einiges dabei:
schaus mir gleich durch und versuche die von dir genannten Punkte zu überarbeiten.

Das mit 'with' ist z.B deswegen, weil ich vor Kurzem gesehen hab, dass es so auch geht
und es mal ausprobiert hab.

Das Wörterbuch ist die Lösung für mein Speicherproblem?, werd mal versuchen, das umzusetzen.

melde mich wieder, sobald ich weiterkomme.
Benutzeravatar
__blackjack__
User
Beiträge: 13533
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Also bei mir stürzt Qt nicht ab, sondern ich bekomme eine erwartbare Ausnahme:

Code: Alles auswählen

Traceback (most recent call last):
  File "./forum21.py", line 62, in save
    pickle.dump(raumjetzt, file)
AttributeError: Can't pickle local object 'EmptyWindow.initialize.<locals>.Room'
Pickle muss an die Klasse kommen können. Das serialisieren könnte theoretisch noch funktionieren, aber wenn man das wieder laden möchte, muss `pickle` über den qualifizierten Namen an den Datentyp kommen können, denn ohne kann das Objekt nicht wieder hergestellt werden. Pickle serialisiert die Daten und nicht die Datentypen. Datentypen werden als qualifizierter Name serialisiert.

Code: Alles auswählen

- (void)countSheep {
    unsigned int sheep = 0;
    while ( ! [self isAsleep]) { ++sheep; }
}
narpfel
User
Beiträge: 658
Registriert: Freitag 20. Oktober 2017, 16:10

@__blackjack__: Das „exit code -1073740791 (0xC0000409)“ bekommt man unter PyCharm, wenn eine Exception in der Qt-Mainloop auftritt.

@MartinausWien: Falls du tatsächlich PyCharm benutzt und das nicht nur ein Zufall ist, dass das der gleiche Fehler ist: Ich kann nur davon abraten, Qt-Programme in PyCharm zu starten. Dass es Exceptions verschluckt, macht es in meinen Augen absolut unbrauchbar, damit Programme zu entwickeln, die länger als 10 Zeilen sind. Starte das Programm außerhalb von PyCharm, dann ist es viel einfacher, Fehler zu finden.
MartinausWien
User
Beiträge: 15
Registriert: Dienstag 15. Dezember 2020, 00:41

Hallo, __blackjack__, hallo Sirius3

Vielen Dank für die vielen Hilfen. werde mir das mit dem qualifizierten Datentyp genauer ansehen.
weiss noch nicht genau wie das ist. wenn ich das Qualifizieren kappiert hab, schreib ichs rein.
...hab jetzt grade gelesen, ja ich führe PyQt in PyCharm aus?? wenn das schlecht sein soll..mh :idea:, super Tipp, danke.

Ich habs jetzt mal nach Vorschlag von Sirius mit einem Wörterbuch versucht, um das Raumobjekt über raumjetzt.raumname als bin speichern zu können.
Jetzt scheint das Speichern und Laden zu funktionieren,
nach dem Zurückladen wandle ich deserial (ehemals raumjetzt.raumname, gibt sonst wieder ein Problem)
übers Dict. wieder ins Raumobjekt um und gebe es dann wieder der Funktion self.raum_enter() weiter.
Was sagt ihr dazu?

So hab ichs jetzt geändert.

Code: Alles auswählen

    self.dict = {self.wohnzimmer.raumname: self.wohnzimmer,
                        self.gang.raumname: self.gang,
                        self.schlafzimmer.raumname: self.schlafzimmer}
    
    
    def load(self):

        with open('file.txt', 'r') as a:
            entries = [e.strip() for e in a]
            self.list.clear()
            self.list.insertItems(0, entries)

        with open("objekt.bin", 'rb') as file:
            deserial = pickle.load(file)
            print(deserial)
            if deserial in self.dict:
                self.raum_enter(self.dict[deserial])



    def save(self):

        with open("file.txt", "w") as a:
            a.write('\n'.join(self.list.item(i).text() for i in range(self.list.count())))

        with open("objekt.bin", 'wb') as file:
            pickle.dump(raumjetzt.raumname, file)

MartinausWien
User
Beiträge: 15
Registriert: Dienstag 15. Dezember 2020, 00:41

narpfel hat geschrieben: Dienstag 15. Dezember 2020, 22:08 @__blackjack__: Das „exit code -1073740791 (0xC0000409)“ bekommt man unter PyCharm, wenn eine Exception in der Qt-Mainloop auftritt.

@MartinausWien: Falls du tatsächlich PyCharm benutzt und das nicht nur ein Zufall ist, dass das der gleiche Fehler ist: Ich kann nur davon abraten, Qt-Programme in PyCharm zu starten. Dass es Exceptions verschluckt, macht es in meinen Augen absolut unbrauchbar, damit Programme zu entwickeln, die länger als 10 Zeilen sind. Starte das Programm außerhalb von PyCharm, dann ist es viel einfacher, Fehler zu finden.
Oha, genau das ist es, ich verwende PyCharm, also kein Zufall, super Tipp wiegesagt.
hab mich schon gewundert, immer nur solche Fehler zu bekommen, die überhaupt keinen Hinweis geben. :o
Sirius3
User
Beiträge: 18051
Registriert: Sonntag 21. Oktober 2012, 17:20

Du solltest die Raumdatenstruktur gleich richtig erzeugen, die Attribute sind nicht mehr nötig:

Code: Alles auswählen

class Room:
    def __init__(self, raumname, beschreibung, exits=None):
        self.raumname = raumname
        self.beschreibung = beschreibung
        self.exits = {} if exits is None else exits


def initialize_rooms():
    rooms = {
        "Wohnzimmer": Room("Wohnzimmer",
            "Du bist im Wohnzimmer.\n"
            "In der Mitte des Raumes steht deine bequeme 'Lockdowncouch'.\n"
            "Im Osten ist eine Türe. Sie steht offen.\n",
            exits={"osten": "Gang"),
        "Gang": Room("Gang",
            "Du bist auf einem Gang.\n"
            "Im Westen führt die Türe ins Wohnzimmer.\n"
            "Im Süden geht es ins Schlafzimmer.\n"
            "Im Osten ist die Eingangstüre, sie ist versperrt\n",
            exits={"westen": "Wohnzimmer", "süden": "Schlafzimmer"}),
        "Schlafzimmer": Room("Schlafzimmer",
            "Du bist im Schlafzimmer.\n"
            "Hier steht ein Bett.\n"
            "Irgendetwas liegt auf dem Bett.\n"
            "Im Norden geht es zu einem Gang.\n",
            exits={"norden": "Gang"}),
    }
    return rooms
`dict` ist ein schlechter Attributname, weil der so gar nichts über den Inhalt sagt.
MartinausWien
User
Beiträge: 15
Registriert: Dienstag 15. Dezember 2020, 00:41

Hallo nochmal:

also ich habe jetzt die neue Datenstruktur mal so wie im Codebeispiel angelegt.

Wo kann da der Fehler liegen, das das pickeln trotzdem nicht klappt?
ohne PYQT funktioniert es. das müsste dann im Gui Rahmen genauso gehen..?
Eine Idee was ich ändern müsste?

Code: Alles auswählen

class EmptyWindow(QMainWindow):
    def __init__(self):
        super().__init__()  # der Constructor wird gebuildet
    
        class Room:
            def __init__(self, raumname, beschreibung, exits=None):
                self.raumname = raumname
                self.beschreibung = beschreibung
                self.exits = {} if exits is None else exits

        self.rooms = {
             "Wohnzimmer": Room("Wohnzimmer",
                               "Du bist im Wohnzimmer.\n"
                               "In der Mitte des Raumes steht deine bequeme 'Lockdowncouch'.\n"
                               "Im Osten ist eine Türe. Sie steht offen.\n",
                               exits={"osten": "Gang"}),
             "Gang": Room("Gang",
                         "Du bist auf einem Gang.\n"
                         "Im Westen führt die Türe ins Wohnzimmer.\n"
                         "Im Süden geht es ins Schlafzimmer.\n"
                         "Im Osten ist die Eingangstüre, sie ist versperrt\n",
                         exits={"westen": "Wohnzimmer", "süden": "Schlafzimmer"}),
             "Schlafzimmer": Room("Schlafzimmer",
                                 "Du bist im Schlafzimmer.\n"
                                 "Hier steht ein Bett.\n"
                                 "Irgendetwas liegt auf dem Bett.\n"
                                 "Im Norden geht es zu einem Gang.\n",
                                 exits={"norden": "Gang"}),
        }
    def save(self):        
        with open("objekt.bin", 'wb') as file:
            pickle.dump(self.rooms["Wohnzimmer"], file)
Sirius3
User
Beiträge: 18051
Registriert: Sonntag 21. Oktober 2012, 17:20

Nochmal, die Klasse hat in der __init__-Methode nichts verloren, die muß auf oberster Ebene stehen, dann funktioniert das, würde ich aber trotzdem nicht machen, weil es ja reicht, einfach nur den Namen des Raums in die Datei zu schreiben.
Benutzeravatar
__blackjack__
User
Beiträge: 13533
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Vielleicht nochmal ganz deutlich und allgemein: Klassendefinitionen gehören auf Modulebene. Es gibt nur ganz wenige und ziemlich spezielle Fälle wo Klassen nicht auf Modulebene stehend sinnvoll sind.

Ebenfalls allgemeiner Rat: `pickle` ist kein gutes Format um Daten längerfristig zu speichern. Es ist abhängig von der Codestruktur und ein Python-spezifisches Format. Das ist okay für Caches oder um Daten für eine Datenübertragung zu einem anderen Python-Prozess zu (de)serialisieren. Zum Speichern von Daten sollte man ansonsten besser ein standardisiertes, sprachunabhängiges Format verwenden.

Code: Alles auswählen

- (void)countSheep {
    unsigned int sheep = 0;
    while ( ! [self isAsleep]) { ++sheep; }
}
MartinausWien
User
Beiträge: 15
Registriert: Dienstag 15. Dezember 2020, 00:41

Hallo Leute,
danke Eurer Hilfe hab ich viel dazulernen können, vielen Dank.
Ich war durch Eure Antworten schon auf der richtigen Spur, es hat nur noch ein Funke gefehlt.
dann hab ich mir nochmal helfen lassen und jetzt gibt es die Lösung: Juhu
Im Prinzip 2. Schritte:
Ich habe manchmal beim Herumprobieren nur einen der Schritte richtig umgestellt und dann lief es nicht weil der andere wieder nicht gepasst hat.

1. Die Klasse einfach auf die Global/Modulebene setzen,....danke Sirius3 und __blackjack__: jetzt hab ichs endlich verstanden.
2. global kann ich mir schenken, stattdessen self.raumjetzt = None vorher schon angeben und dann self.raumjetzt weiterverwenden.

Dann klappt es auch mit dem pickle.dump von self.raumjetzt ohne Probleme.
Sirius3
User
Beiträge: 18051
Registriert: Sonntag 21. Oktober 2012, 17:20

Jetzt fehlt nur noch der Schritt, gar kein pickle zu verwenden.
MartinausWien
User
Beiträge: 15
Registriert: Dienstag 15. Dezember 2020, 00:41

Sirius3 hat geschrieben: Donnerstag 17. Dezember 2020, 06:44 Jetzt fehlt nur noch der Schritt, gar kein pickle zu verwenden.
Hi Sirius, welches Seralisationsformat um den Raum(Spielstand) abzuspeichern ist besser geeignet?
Kannst du mir bitte ein paar Stichworte geben.
danke lg Martin
Benutzeravatar
__blackjack__
User
Beiträge: 13533
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@MartinausWien: Wenn es tatsächlich nur ein einzelner Raumname als Zeichenkette ist, wäre das einfachste eine Textdatei die diesen einen Namen enthält. Ansonsten wäre JSON eine Möglichkeit für die es in der Standardbibliothek ein Modul gibt.

Code: Alles auswählen

- (void)countSheep {
    unsigned int sheep = 0;
    while ( ! [self isAsleep]) { ++sheep; }
}
MartinausWien
User
Beiträge: 15
Registriert: Dienstag 15. Dezember 2020, 00:41

__blackjack__ hat geschrieben: Donnerstag 17. Dezember 2020, 10:02 @MartinausWien: Wenn es tatsächlich nur ein einzelner Raumname als Zeichenkette ist, wäre das einfachste eine Textdatei die diesen einen Namen enthält. Ansonsten wäre JSON eine Möglichkeit für die es in der Standardbibliothek ein Modul gibt.
Hi, eine Textdatei habe ich bei der Itemliste (Schwert, Stein etc.) verwendet und die wird bei Spielstandsicherung als .txt abgespeichert.

Beim Raum handelt es sich um ein ganzes Klassenobjekt (ein Raum der Klasse Room) mit all seinen Attributen.
Dieses brauche ich nach dem Laden wieder, da z.B auch die Ausgänge zu anderen Räumen etc. in der Klasse definiert sind.
Würde ich nur den Raumnamen als .txt abspeichern, müsste ich diesen dann nach dem Laden wieder irgendwie dem Objekt zuordnen, über
ein Wörterbuch etc, was auch geht, aber mehr Schritte benötigt, als wenn der Raum gleich wieder "da" ist.

JSON, will ich mir unbedingt mal ansehen, habe mich damit noch gar nicht beschäftigt, aber ist mir immer wieder mal untergekommen,
plattformunabhängiger Datenaustausch, hm, wenn du es jetzt auch gleich erwähnst..
danke mal __Blackjack__. , lg Martin
MartinausWien
User
Beiträge: 15
Registriert: Dienstag 15. Dezember 2020, 00:41

kurzer Nachtrag: hab jetzt nochmal bissl recherchiert.
Da gibt es ja viele Beiträge zu z.B JSON vs. Pickle. Was ist schneller, Vorteile Nachteile etc. , sehr interessant.
angeblich ist Pickle bei komplexer Objektserialisierung viel schneller, JSON dafür bei fast allem anderen, funktioniert aber nicht bei allen Python Objekten.
Da ich ja mit Pickle eh ein Objekt speichere wird es denk ich kein großer Nachteil sein fürs Objekt pickle zu verwenden.
JSON werde ich jetzt mal studieren, wieder was zu lernen cool. lg
Antworten