You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:在约束中使用om.slicer时SqliteRecorder崩溃问题

SqliteRecorder崩溃问题:使用om.slicer约束时JSON序列化失败

问题描述

当在OpenMDAO中为约束配置使用om.slicer时,SqliteRecorder会在启动阶段直接崩溃,抛出TypeError: Object of type slice is not JSON serializable错误。根源在于slice对象无法被Python默认的JSON编码器处理,而SqliteRecorder在记录变量配置信息时,会尝试把包含om.slicer的约束设置转为JSON格式,最终触发序列化失败。

错误追踪栈

Traceback (most recent call last):
  File "test_slicer.py", line 38, in <module>
    p.run_model()
  File "/Users/frza/git/OpenMDAO/openmdao/core/problem.py", line 610, in run_model
    self.final_setup()
  File "/Users/frza/git/OpenMDAO/openmdao/core/problem.py", line 959, in final_setup
    self._setup_recording()
  File "/Users/frza/git/OpenMDAO/openmdao/core/problem.py", line 728, in _setup_recording
    self._rec_mgr.startup(self)
  File "/Users/frza/git/OpenMDAO/openmdao/recorders/recording_manager.py", line 91, in startup
    recorder.startup(recording_requester)
  File "/Users/frza/git/OpenMDAO/openmdao/recorders/sqlite_recorder.py", line 394, in startup
    var_settings_json = json.dumps(var_settings)
  File "/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type slice is not JSON serializable

复现代码

以下是可复现该问题的最小示例(取自openmdao/core/tests/test_group.py):

import numpy as np
import openmdao.api as om
from openmdao.api import SqliteRecorder

arr_order_1x1 = np.array([1, 2, 3, 4])

class SlicerComp(om.ExplicitComponent):
    def setup(self):
        self.add_input('x', np.ones(4))
        self.add_output('y', 1.0)

    def compute(self, inputs, outputs):
        outputs['y'] = np.sum(inputs['x'])**2.0

p = om.Problem()
p.model.add_subsystem('indep', om.IndepVarComp('x', arr_order_1x1))
p.model.add_subsystem('C1', SlicerComp())
p.model.connect('indep.x', 'C1.x')
p.model.add_constraint('indep.x', indices=om.slicer[2:])
p.model.add_objective('C1.y')

p.setup()
p.run_model()

precorder = SqliteRecorder('poptimization.sqlite')
p.recording_options['record_desvars'] = True
p.recording_options['record_constraints'] = True
p.recording_options['record_objectives'] = True
p.add_recorder(precorder)

p.setup()
p.run_model()
p.cleanup()

环境信息

  • 操作系统:OS X 10.15.5、CentOS
  • Python版本:3.6.1、3.8.5
  • OpenMDAO版本:master分支

解决方案

永久修复(修改OpenMDAO源码)

需要给SqliteRecorder添加自定义JSON编码器来处理slice对象,具体操作:

  1. 在openmdao/recorders/sqlite_recorder.py文件中,添加自定义编码器类:
import json

class SliceEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, slice):
            return {
                '__type__': 'slice',
                'start': obj.start,
                'stop': obj.stop,
                'step': obj.step
            }
        return super().default(obj)
  1. 修改文件中startup方法里的json.dumps调用,指定使用自定义编码器:
var_settings_json = json.dumps(var_settings, cls=SliceEncoder)

临时 workaround(无需修改源码)

暂时替换om.slicer的用法,改用列表形式的索引。比如把indices=om.slicer[2:]改成indices=[2,3],这样就能绕过序列化问题,正常使用SqliteRecorder。

内容的提问来源于stack exchange,提问作者frza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 14:52:39