有没有一种方法可以序列化 class 以便可以独立于其原始脚本对其进行反序列化?
Is there a way to serialize a class such that it can be unserialized independent of its original script?
或者,有没有一种方法可以从脚本中序列化并保存 class,如果脚本被删除,它仍然可以加载?
考虑同一目录中的三个 Python 脚本:
test.py
import pickle
import test_class_pickle
tc = test_class_pickle.Test()
pickle.dump(tc, open("/home/user/testclass", "wb"))
test_class_pickle.py
class Test:
def __init__(self):
self.var1 = "Hello!"
self.var2 = "Goodbye!"
def print_vars(self):
print(self.var1, self.var2)
test_class_unpickle.py
import pickle
tc = pickle.load(open("/home/user/testclass", "rb"))
print(tc.var1, tc.var2)
当我 运行 test.py
时,它从 test_class_pickle
导入 Test
class,创建它的实例,并将其保存到文件中使用 pickle
。当我 运行 test_class_unpickle.py
时,它会按预期将 class 加载回内存。
但是,当我再次删除 test_class_pickle.py
和 运行 test_class_unpickle.py
时,它抛出这个异常:
Traceback (most recent call last):
File "/home/sam/programs/python/testing/test_class_unpickle.py", line 3, in <module>
tc = pickle.load(open("/home/sam/testclass", "rb"))
ModuleNotFoundError: No module named 'test_class_pickle'
有没有一种方法可以将 class 个实例保存到文件中而不依赖于原始脚本的持续存在?如果我不必使用 json
之类的东西就好了(这需要我获取 class 的所有属性的列表,将它们写入字典等),因为所有 classes 也在处理其他 classes,这些 classes 正在处理其他 classes,等等,并且每个 class 都有几个处理数据的函数。
这是让 dill
做到这一点的方法。 Dill 仅存储 __main__
中定义的对象的定义,而不存储单独模块中的对象定义。以下函数在 __main__
中重新定义了一个单独的模块,因此它们 将 存储在 pickle 文件中。基于这个答案 .
test.py
import dill
from pathlib import Path
import test_class_pickle
def mainify_module(module):
import __main__ # This module.
import importlib, inspect, sys
code = inspect.getsource(module)
spec = importlib.util.spec_from_loader(module.__name__, loader=None)
module_obj = importlib.util.module_from_spec(spec)
exec(code, __main__.__dict__)
sys.modules[module.__name__] = module_obj # Replace in cache.
globals()[module.__name__] = module_obj # Redefine.
pkl_filepath = Path('testclass.pkl')
pkl_filepath.unlink(missing_ok=True) # Delete any existing file.
mainify_module(test_class_pickle)
tc = Test('I Am the Walrus!')
with open(pkl_filepath, 'wb') as file:
dill.dump(tc, file)
print(f'dill pickle file {pkl_filepath.name!r} created')
test_class_pickle.py
class Test:
def __init__(self, baz):
self.var1 = "Hello!"
self.var2 = "Goodbye!"
self.foobar = baz
def print_vars(self):
print(self.var1, self.var2, self.foobar)
test_class_unpickle.py
import dill
pkl_filepath = 'testclass.pkl'
with open(pkl_filepath, 'rb') as file:
tc = dill.load(file)
tc.print_vars() # -> Hello! Goodbye! I Am the Walrus!
或者,有没有一种方法可以从脚本中序列化并保存 class,如果脚本被删除,它仍然可以加载?
考虑同一目录中的三个 Python 脚本:
test.py
import pickle
import test_class_pickle
tc = test_class_pickle.Test()
pickle.dump(tc, open("/home/user/testclass", "wb"))
test_class_pickle.py
class Test:
def __init__(self):
self.var1 = "Hello!"
self.var2 = "Goodbye!"
def print_vars(self):
print(self.var1, self.var2)
test_class_unpickle.py
import pickle
tc = pickle.load(open("/home/user/testclass", "rb"))
print(tc.var1, tc.var2)
当我 运行 test.py
时,它从 test_class_pickle
导入 Test
class,创建它的实例,并将其保存到文件中使用 pickle
。当我 运行 test_class_unpickle.py
时,它会按预期将 class 加载回内存。
但是,当我再次删除 test_class_pickle.py
和 运行 test_class_unpickle.py
时,它抛出这个异常:
Traceback (most recent call last):
File "/home/sam/programs/python/testing/test_class_unpickle.py", line 3, in <module>
tc = pickle.load(open("/home/sam/testclass", "rb"))
ModuleNotFoundError: No module named 'test_class_pickle'
有没有一种方法可以将 class 个实例保存到文件中而不依赖于原始脚本的持续存在?如果我不必使用 json
之类的东西就好了(这需要我获取 class 的所有属性的列表,将它们写入字典等),因为所有 classes 也在处理其他 classes,这些 classes 正在处理其他 classes,等等,并且每个 class 都有几个处理数据的函数。
这是让 dill
做到这一点的方法。 Dill 仅存储 __main__
中定义的对象的定义,而不存储单独模块中的对象定义。以下函数在 __main__
中重新定义了一个单独的模块,因此它们 将 存储在 pickle 文件中。基于这个答案 .
test.py
import dill
from pathlib import Path
import test_class_pickle
def mainify_module(module):
import __main__ # This module.
import importlib, inspect, sys
code = inspect.getsource(module)
spec = importlib.util.spec_from_loader(module.__name__, loader=None)
module_obj = importlib.util.module_from_spec(spec)
exec(code, __main__.__dict__)
sys.modules[module.__name__] = module_obj # Replace in cache.
globals()[module.__name__] = module_obj # Redefine.
pkl_filepath = Path('testclass.pkl')
pkl_filepath.unlink(missing_ok=True) # Delete any existing file.
mainify_module(test_class_pickle)
tc = Test('I Am the Walrus!')
with open(pkl_filepath, 'wb') as file:
dill.dump(tc, file)
print(f'dill pickle file {pkl_filepath.name!r} created')
test_class_pickle.py
class Test:
def __init__(self, baz):
self.var1 = "Hello!"
self.var2 = "Goodbye!"
self.foobar = baz
def print_vars(self):
print(self.var1, self.var2, self.foobar)
test_class_unpickle.py
import dill
pkl_filepath = 'testclass.pkl'
with open(pkl_filepath, 'rb') as file:
tc = dill.load(file)
tc.print_vars() # -> Hello! Goodbye! I Am the Walrus!