I have a python script that is basically a team builder. However it is not running constantly as I am running it locally for now. I want users to be able to access their previously created team and so what would be the best way to store a dictionary of a custom object?
I have two classes, Team
and Character
. The Team
class has an attribute that is a list of Character
instances. And each Team
is stored as a value in a dictionary with a user_id as the key.
Here is a basic outline:
master = {a_user_id:TrainerObject,another_user_id:TrainerObject,..}
class Trainer:
def __init__(self, user):
self.id = user.id # int
self.name = user.name # str
self.icon = user.icon # str, just a url link
self.team = [] # List of Characters
class Character:
def __init__(self, slot, name, skills, item=None):
self.slot = slot # int
self.name = name # str
self.skills = skills # dictionary of all str
self.item = item # str
with open('master.pkl','wb') as f:
pickle.dump(master,f)
Error:
Ignoring exception in command store:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/discord/ext/commands/core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "/Users/roopesh_m/Documents/Python/Coromon Battlesim/cogs/teambuild.py", line 565, in store
pickle.dump(master,f)
TypeError: cannot pickle 'weakref' object
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/discord/ext/commands/bot.py", line 939, in invoke
await ctx.command.invoke(ctx)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/discord/ext/commands/core.py", line 863, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/discord/ext/commands/core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: cannot pickle 'weakref' object
Edit: I have tried using pickle to store the dictionary, however I get a 'weakref' error when attempting to dump the dictionary
Edit2: Specified data types of class attributes
Edit3: Added pickle attempt and error
CodePudding user response:
The easiest way is to use pickle
, a module in the standard library intended for this purpose.
import pickle
def save(save_file_path, team):
with open(save_file_path, 'wb') as f:
pickle.dump(team, f)
def load(save_file_path):
with open(save_file_path, 'rb') as f:
return pickle.load(f)
# Example
save('version_1.team', master)
print(load('version_1.team')
You may need to handle some exceptions when loading if the file doesn't exist, but I left that out for simplicity. The reference for pickle
can be found here.
CodePudding user response:
Use dataclass
dacite
. See the example below.
The code shows how we take a dict, convert it to a Trainer, back to dict and back to Trainer.
This is actually what you are looking for.
from typing import List,Optional
from dataclasses import dataclass,asdict
from dacite import from_dict
@dataclass
class Character:
slot:int
name:str
skills:str
item:Optional[str]
@dataclass
class Trainer:
id :int
name:str
icon:str
team: List[Character]
data = {'id':3,'name':'jack','icon':'something','team':[{'slot':9,'name':'Jim','skills':'well','item':'zoot'}]}
trainer = from_dict(data_class=Trainer,data=data)
print(trainer)
data = asdict(trainer)
print(data)
trainer = from_dict(data_class=Trainer,data=data)
print(trainer)