1

In python, I am trying to store a list to a file. I've tried pickle, json, etc, but none of them support classes being inside those lists. I can't sacrifice the lists or the classes, I must maintain both. How can I do it?

My current attempt:

try:
    with open('file.json', 'r') as file:
        allcards = json.load(file)
except:
    allcards = []

def saveData(list):
    with open('file.json', 'w') as file:
        print(list)
        json.dump(list, file, indent=2)

saveData is called elsewhere, and I've done all the testing I can and have determined the error comes from trying to save the list due to it's inclusion of classes. It throws me the error

Object of type Card is not JSON serializable

whenever I do the JSON method, and any other method doesn't even give errors but doesn't load the list when I reload the program.

Edit: As for the pickle method, here is what it looks like:

try:
    with open('allcards.dat', 'rb') as file:
        allcards = pickle.load(file)
        print(allcards)
except:
    allcards = []

class Card():
    def __init__(self, owner, name, rarity, img, pack):
        self.owner = str(owner)
        self.name = str(name)
        self.rarity = str(rarity)
        self.img = img
        self.pack = str(pack)

def saveData(list):
    with open('allcards.dat', 'wb') as file:
        pickle.dump(list, file)

When I do this, all that happens is the code runs as normal, but the list is not saved. And the print(allcards) does not trigger either which makes me believe it's somehow not detecting the file or causing some other error leading to it just going straight to the exception. Also, img is supposed to always a link, in case that changes anything.

I have no other way I believe I can help solve this issue, but I can post more code if need be.

Please help, and thanks in advance.

  • 1
    Possible solution: https://stackoverflow.com/questions/10252010/serializing-class-instance-to-json , see answer #1 – nicomp Apr 08 '20 at 17:44
  • What was the problem when you tried to use pickle? – mkrieger1 Apr 08 '20 at 17:46
  • This is tough to answer without the code for the Card class. – Eric Truett Apr 08 '20 at 17:47
  • You aren't trying to put *classes* in a list, you are trying to put instances of a class. In any case, pickle **does** support arbitrary python objects, so please show what you've tried and **exactly** how it doesn't work. – juanpa.arrivillaga Apr 08 '20 at 17:48
  • mkrieger1, it doesn't throw errors, but when I restart the program the list just doesn't load properly. juanpa.arrivillaga, I have edited the post to include my pickle attempt, but it doesn't throw any errors, but it still doesn't save properly. – Maple Maelstrom Apr 08 '20 at 19:44
  • nicomp, it doesn't help as far as I can understand (though I may be wrong, please tell me if I can use it) because I need to be able to save an infinite amount of instances of Card. That allows me to serialize a singular instance, and I don't see a way to serialize all that are in a list that can be infinite in length. – Maple Maelstrom Apr 08 '20 at 20:55

3 Answers3

0

Could you confirm if this works:

try:
    with open('file.json', 'r') as file:
        allcards = json.load(file)
except:
    allcards = []

def saveData(list):
    with open('file.json', 'w') as file:
        print(list)
        json.dump(list.__dict__, file, indent=2)
Harshit Jindal
  • 683
  • 4
  • 22
  • This throws the error: "discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'list' object has no attribute '__dict__'" I'm working with discord.py but I don't think that should change anything – Maple Maelstrom Apr 08 '20 at 19:36
-1

Python's built-in pickle module does not support serializing a python class, but there are libraries that extend the pickle module and provide this functionality. Drill and Cloudpickle both support serializing a python class and has the exact same interface as the pickle module.

Dill: https://github.com/uqfoundation/dill

Cloudpickle: https://github.com/cloudpipe/cloudpickle

Chaoyu
  • 985
  • 7
  • 16
-1

//EDIT The article linked below is good, but I've written a bad example. This time I've created a new snippet from scratch -- sorry for making it earlier more complicated than it should.

import json

class Card(object):
    @classmethod
    def from_json(cls, data):
        return cls(**data)

    def __init__(self, figure, color):
        self.figure = figure
        self.color = color

    def __repr__(self):
        return f"<Card: [{self.figure} of {self.color}]>"

def save(cards):
    with open('file.json', 'w') as f:
        json.dump(cards, f, indent=4, default=lambda c: c.__dict__)

def load():
    with open('file.json', 'r') as f:
        obj_list = json.load(f)
        return [Card.from_json(obj) for obj in obj_list]


cards = []
cards.append(Card("1", "clubs"))
cards.append(Card("K", "spades"))
save(cards)

cards_from_file = load()
print(cards_from_file)

Source

Andrew
  • 43
  • 1
  • 5