SymPy相关函数跨会话Pickle加载失败问题排查
问题原因分析
这个错误和SymPy无关,本质是pickle的序列化机制导致的:
- pickle保存函数时,不会序列化函数的代码逻辑,只记录函数的名称和它所在的模块(比如你在同会话脚本中定义的
SymSqr属于__main__模块)。 - 跨会话加载时,pickle会尝试在当前脚本的
__main__模块中查找名为SymSqr的函数,但你的跨会话脚本里没有定义这个函数,因此抛出AttributeError。
解决方案
方案1:将函数放到独立模块(推荐)
把SymSqr函数放到单独的Python模块中,让pickle保存函数的模块路径而非__main__,这样跨会话加载时能正确找到函数定义。
- 创建
sym_functions.py模块:
from sympy import Symbol def SymSqr(xExp): return xExp * xExp
- 修改同会话保存脚本:
import pickle from sym_functions import SymSqr from sympy import Symbol if __name__ == "__main__": fileName = 'temp.pickle' xSym = Symbol('x') # 测试原函数 result = SymSqr(2*xSym) print(f'result = {result}') # 保存函数 with open(fileName, 'wb') as outFle: pickle.dump(SymSqr, outFle) # 同会话加载测试 with open(fileName, 'rb') as inFile: atlFunc = pickle.load(inFile) altResult = atlFunc(2 * xSym) print(f'altResult = {altResult}')
- 跨会话加载脚本:
import pickle from sym_functions import SymSqr # 先导入模块中的函数,确保模块存在该定义 from sympy import Symbol if __name__ == "__main__": fileName = 'temp.pickle' xSym = Symbol('x') # 加载函数 with open(fileName, 'rb') as inFile: loaded_func = pickle.load(inFile) # 测试加载后的函数 result = loaded_func(2 * xSym) print(f'result = {result}')
方案2:用dill替代pickle
dill是pickle的扩展,可以直接序列化函数的代码逻辑,不需要依赖模块中的函数定义。
- 安装dill:
pip install dill
- 修改同会话保存脚本:
import dill from sympy import Symbol def SymSqr(xExp): return xExp * xExp if __name__ == "__main__": fileName = 'temp.dill' xSym = Symbol('x') result = SymSqr(2*xSym) print(f'result = {result}') # 用dill保存函数 with open(fileName, 'wb') as outFle: dill.dump(SymSqr, outFle) # 同会话加载测试 with open(fileName, 'rb') as inFile: atlFunc = dill.load(inFile) altResult = atlFunc(2 * xSym) print(f'altResult = {altResult}')
- 跨会话加载脚本:
import dill from sympy import Symbol if __name__ == "__main__": fileName = 'temp.dill' xSym = Symbol('x') # 用dill加载函数 with open(fileName, 'rb') as inFile: SymSqr = dill.load(inFile) # 测试加载后的函数 result = SymSqr(2 * xSym) print(f'result = {result}')
方案3:临时修复(不推荐用于生产)
在跨会话加载脚本中先定义同名的空函数,让pickle能找到名称匹配的对象,之后会覆盖为加载的函数:
import pickle from sympy import Symbol # 先定义同名函数,让pickle能找到 def SymSqr(xExp): pass if __name__ == "__main__": fileName = 'temp.pickle' xSym = Symbol('x') with open(fileName, 'rb') as inFile: SymSqr = pickle.load(inFile) result = SymSqr(2 * xSym) print(f'result = {result}')
内容的提问来源于stack exchange,提问作者GPU Programmer
相关产品推荐
相关产品推荐

