1

I have a file, memory.txt, and I want to store an instance of the class Weapon() in a dictionary, on the second line.

with open(memorypath(), "r") as f:
    lines = f.readlines()
    inv = inventory()
    if "MAINWEAPON" not in inv or inv["MAINWEAPON"] == "":
        inv["MAINWEAPON"] = f"""Weapon(sw, 0, Ability(0, "0"), ["{name}'s first weapon."], dmg=30, cc=20, str=15)"""
    lines[1] = str(inv) + "\n"
    with open(memorypath(), "w") as f:
        f.writelines(lines)

(inventory and memorypath are from another file I have for utility functions) Though, with what I have, if I get inv["MAINWEAPON"] I'll just get the string, not the class. And I have to store it like a string, or else I'll be getting something like <__main\__.Weapon object at (hexadecimal path thing)>. How do I get the class itself upon getting inv["MAINWEAPON"]? Another thing, too, I feel like I'm making such confusion with newlines, because file memory.txt has 6 lines but gets shortened to 5, please tell me if I'm doing anything wrong.

9
  • 2
    Have you considered the pickle module? Commented Aug 25, 2021 at 20:03
  • 1
    Have you concidered json serialization? Commented Aug 25, 2021 at 20:04
  • @quamrana i'm going to check that out Commented Aug 25, 2021 at 20:08
  • @mama What do you mean? Edit: hmm it's similar to pickle apparently Commented Aug 25, 2021 at 20:08
  • 1
    Yes it is called serialization and deserialization Commented Aug 25, 2021 at 20:16

2 Answers 2

3

If you have a class then you can represent it as a dict and save it as json format.

class Cat:
    name: str
    def __init__(self, name: str):
        self.name = name
    
    def dict(self):
        return {'name': self.name}
    @classmethod
    def from_dict(cls, d):
        return cls(name = d['name'])

Now you can save the class as a json to a file like this:

import json
cat = Cat('simon')
with open('cat.json', 'w') as f:
    json.dump(cat.dict(), f)

And you can load the json again like this:

with open('cat.json', 'r') as f:
    d = json.load(f)
    cat = Cat.from_dict(d)

Update

Since python 3.7 the possilility to make dataclasses has been made, and I am here giving an example of how you can use that to save the classes into a json format.

If you want to use the json file as a database and be able to append new entities to it then you will have to load the file into memory and append the new data and finally override the old json file, the code below will do exactly that.

from dataclasses import dataclass, asdict
import json

@dataclass
class Cat:
    name: str

def load_cats() -> list[Cat]:
    try:
        with open('cats.json', 'r') as fd:
            return [Cat(**x) for x in json.load(fd)]
    except FileNotFoundError:
        return []

def save_cat(c):
    data = [asdict(x) for x in load_cats() + [c]]
    with open('cats.json', 'w') as fd:
        json.dump(data, fd)

c = Cat(name='simon')
save_cat(c)
cats = load_cats()
print(cats)
Sign up to request clarification or add additional context in comments.

8 Comments

Hey, I have 6 lines to store information in the memory file, can I just use lines[1] = json.dumps(dict(cat), f)? Ideally, I want that in a single line. I'm testing it with dumps and loads, apparently they return a string. Also, what is cls()? Is it like bool() but for making a class out of dict?
I think it would have worked perfectly if Weapon didn't have Ability class as an attribute. Right now, it gives me an error: TypeError: Object of type Ability is not JSON serializable
You just need to do the same with Ability and if Ability has another class then repeat
It didn't work, maybe it's because it uses a custom exception class (K_InvalidTrig), in "raise K_InvalidTrig". Do I need to json.dumps Ability? K_InvalidTrig has no attributes.
notice I am not using json.dumps or json.loads in the answer
|
0

A simplest approach I can suggest would be dataclasses.asdict as mentioned; or else, using a serialization library that supports dataclasses. There are a lot of good ones out there, but for this purpose I might suggest dataclass-wizard. Further, if you want to transform an arbitrary JSON object to dataclass structure, you can use the included CLI tool. When serializing, it will autoamtically apply a key transform (snake_case to camelCase) but this is easily customizable as well.

Disclaimer: I am the creator (and maintener) of this library.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.