问题描述
_pickle.PickingError: Can't pick <class 'IOEngine.user_module : attribute loopup
解决方案
报错原因分析
在 Ptrade 量化框架中,系统会在 before_trading_start(隔日开始)、handle_data、after_trading_end 事件后触发持久化信息更新,自动使用 pickle 模块保存全局对象 g 中的变量。
当您遇到 _pickle.PickingError: Can't pick <class 'IOEngine.user_module : attribute loopup 报错时,是因为您在全局变量 g 中挂载了无法被序列化的对象。根据 Ptrade 官方文档说明:涉及到IO(打开的文件,实例化的类对象、模块等)的对象是不能被序列化的。
官方解决方案
为了解决这个问题,Ptrade 提供了一个机制:全局变量 g 中以双下划线 __ 开头的变量会被视为私有变量,持久化时将自动跳过,不会被保存。
因此,您只需要将无法序列化的对象(如类实例、IO对象、数据库连接等)在赋值给 g 时,变量名加上 __ 前缀即可。
代码修复示例
错误写法(会引发 PickingError)
class MyCustomModule(object):
pass
def initialize(context):
g.security = "600570.SS"
set_universe(g.security)
# 错误:直接挂载无法序列化的类实例或IO对象
g.my_module = MyCustomModule()
正确写法(使用双下划线跳过持久化)
class MyCustomModule(object):
def print_info(self):
log.info("模块调用成功")
def initialize(context):
g.security = "600570.SS"
set_universe(g.security)
# 正确:变量名以 '__' 开头,落地持久化信息时会跳过保存该变量
g.__my_module = MyCustomModule()
def handle_data(context, data):
# 盘中正常调用私有变量中定义的方法
g.__my_module.print_info()
总结注意事项
- 检查您的
initialize函数,找出所有赋值给g的自定义类实例、文件句柄或第三方模块。 - 将它们的变量名统一修改为
g.__变量名的形式。 - 确保在策略的其他地方(如
handle_data)调用时,也同步修改为带有双下划线的变量名。