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

Python类静态方法用globals()写JSON失效但类外函数正常的原因

问题原因

核心差异是不同作用域下globals()返回的命名空间不一致:

  • 定义在resepi.py模块中的静态方法save,调用globals()时返回的是resepi.py模块本身的全局命名空间。你在交互命令行中创建的unit_35844等实例,存储在交互式终端的全局命名空间中,并不在resepi.py的模块全局空间里,所以遍历的时候找不到匹配的resepi类实例,最终返回空字典。
  • 你在交互命令行直接定义的save2函数,调用globals()时返回的就是当前交互终端的全局命名空间,里面正好包含了你创建的所有resepi实例,所以逻辑可以正常运行。

另外需要注意:你当前用globals()+eval()的实现方式风险很高,一旦全局空间里有不可序列化的对象、或者恶意构造的变量名,会直接触发安全问题或者运行报错,更推荐用类变量跟踪实例的实现方式。

修复方案

方案1:修改静态方法接收全局命名空间作为参数

修改resepi类的save方法:

@staticmethod
def save(global_vars):
    all_units_info = {name: eval(name, global_vars).__dict__ for name in list(global_vars) if isinstance(eval(name, global_vars), resepi)}
    with open('resepi_log_all.json', 'w') as file:
        json.dump(all_units_info, file, indent=4)
    print(all_units_info)

调用时传入当前环境的全局变量即可:

resepi.save(globals())

方案2(更推荐):用类变量跟踪实例,完全避免操作全局命名空间

修改resepi类的实现:

class resepi:
    # 新增类变量存储所有实例
    all_instances = []
    def __init__ (self, serial_number):
        serial_number = int(serial_number)
        self.serial_number = serial_number
        self.ftp, self.type = ftp(serial_number)
        self.folder = 'C:\\Users\\17037\\Documents\\' + str(serial_number)
        # 初始化时把当前实例加入类变量
        resepi.all_instances.append(self)
    ...
    @staticmethod
    def save():
        all_units_info = {f"unit_{inst.serial_number}": inst.__dict__ for inst in resepi.all_instances}
        with open('resepi_log_all.json', 'w') as file:
            json.dump(all_units_info, file, indent=4)
        print(all_units_info)

这种实现不依赖外部全局命名空间,不管在哪调用resepi.save()都能正常导出所有实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 13:57:04