我有一個 Python 腳本,它基本上是一個團隊構建器。然而,它并沒有持續運行,因為我現在在本地運行它。我希望用戶能夠訪問他們以前創建的團隊,那么存盤自定義物件字典的最佳方式是什么?
我有兩個班級,Team和Character. 本Team類有一個串列中的屬性Character實體。并且每個Team都作為值存盤在字典中,以 user_id 作為鍵。
下面是一個基本的大綱:
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)
錯誤:
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
編輯:我曾嘗試使用 pickle 來存盤字典,但是在嘗試轉儲字典時出現“weakref”錯誤
Edit2:類屬性的指定資料型別
Edit3:添加了泡菜嘗試和錯誤
uj5u.com熱心網友回復:
最簡單的方法是使用pickle,標準庫中用于此目的的模塊。
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')
如果檔案不存在,您可能需要在加載時處理一些例外,但為了簡單起見,我將其省略。pickle可以在此處找到的參考。
uj5u.com熱心網友回復:
使用dataclass dacite。請參閱下面的示例。
代碼顯示了我們如何獲取 dict,將其轉換為 Trainer,再回傳 dict 并回傳 Trainer。
這實際上就是您要尋找的。
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)
uj5u.com熱心網友回復:
您可以使用該dataclass-wizard庫,它執行相對較快的 JSON(反)序列化。我對pickle下面的庫進行了計時,看起來性能大致相同。
注意:下面的示例應該適用于包含
__future__匯入的Python 3.7
from __future__ import annotations
import json
import pickle
from dataclasses import dataclass, asdict
from timeit import timeit
from dataclass_wizard import fromdict
@dataclass
class Trainer:
id: int
name: str
icon: str
team: list[Character]
@dataclass
class Character:
slot: int
name: str
skills: dict[str, str]
item: str | None
master = Trainer(12345, 'Johnny Smidt', 'The Great Icon 123',
team=[Character(7, 'Jim Raynor', {'A1': 'Catching Criminals'}, item='Pistol'),
Character(321, 'Tom Rebel', {'C3': 'Squirrel Hunting'}, item='Snare')],
)
def save(save_file_path, team):
with open(save_file_path, 'wb') as f:
pickle.dump(team, f)
def save2(save_file_path, team):
with open(save_file_path, 'w') as f:
json.dump(asdict(team), f)
def load(save_file_path):
with open(save_file_path, 'rb') as f:
return pickle.load(f)
def load2(save_file_path):
with open(save_file_path, 'rb') as f:
return fromdict(Trainer, json.load(f))
# Example
n = 1_000
print('pickle -> save: ', timeit("save('version_1.team', master)", number=n, globals=globals()))
print('dataclass -> save: ', timeit("save2('version_1.json', master)", number=n, globals=globals()))
print('pickle -> load: ', timeit("load('version_1.team')", number=n, globals=globals()))
print('dataclass -> load: ', timeit("load2('version_1.json')", number=n, globals=globals()))
# assert that Trainer object loaded from pickle/json have the same data
assert load('version_1.team') == load2('version_1.json')
print()
print(load2('version_1.json'))
結果 - 在 Mac OS Big Sur 上測驗,運行 Python 3.10.0
pickle -> save: 0.18621111599986762
dataclass -> save: 0.38911844700032816
pickle -> load: 0.18183052699987456
dataclass -> load: 0.06633681200037245
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/358171.html
