Python 如何解决循环参考检测问题

Python 如何解决循环参考检测问题,python,json,type-conversion,toml,Python,Json,Type Conversion,Toml,我需要将json转换成toml格式 当我运行以下代码时,它返回一个错误 import toml toml_config = toml.dumps(data) 其中,数据为: {“general”:{“log_level”:{“value”:“4”,“editable”:“true”,“description”:“debug=5,info=4,warning=3,error=2,fatal=1,panic=0”},“log_to_syslog”:{“value”:“false”,“editab

我需要将json转换成toml格式

当我运行以下代码时,它返回一个错误

import toml

toml_config = toml.dumps(data)
其中,
数据
为:

{“general”:{“log_level”:{“value”:“4”,“editable”:“true”,“description”:“debug=5,info=4,warning=3,error=2,fatal=1,panic=0”},“log_to_syslog”:{“value”:“false”,“editable”:“true”,“description”:“设置为true时,日志消息正在写入syslog。”}},“postgresql”:{“dsn”:“true”,"postgres://localhost/chirpstack_ns?sslmode\n\n#自动应用数据库迁移。\n#\n#可以手动应用数据库迁移。\n#(请参阅https://github.com/brocaar/chirpstack-network-server/tree/master/migrations)\或使用此设置让ChirpStack应用程序服务器自动迁移到最新状态。请确保在升级ChirpStack应用程序服务器和/或应用迁移时始终进行备份。\n自动迁移max#u open_connections:0,“max#u idle#connections”:2},“redis”:{“servers”:[“localhost:6379]”,“password”:“数据库:0,“集群”:“假”,“主服务器名”:“池大小”:0},“网络服务器”:{“网络id”:“000000”,“重复数据消除延迟”:“200ms”,“设备会话ttl”:“744h0m0s”,“获取下行链路数据延迟”:{“值”:“100ms”,“可编辑”:“真”},“带”:{“名称”:“EU868”,“上行链路驻留时间\400ms”:“假”,“下行链路驻留时间\400ms”:“假”,“上行链路最大驻留时间”\eirp-1,”中继器兼容“:”假“}”,网络设置“{”安装裕度“:10,“接收窗口“:0,“rx1\u延迟“:1,“rx1\u dru偏移“:0,“rx2\u dr“:-1,“rx2\u频率“:-1”,“rx2\u首选”在rx1\u dru lt上“:0,“rx2\u首选”在链路预算上“:”假“,”网关\u首选\u最小裕度“:10,“下行链路\u发送功率”:-1,“禁用\u mac:”命令“:”假“,”假“,”max_mac_command_error_count“:3,“enabled_uplink_channels:[]”,“class_b:{“ping_slot_dr”:0,“ping_slot_frequency”:0},“rejoin_request:{”enabled:“false”,“max_count_n”:0,“max_time_n:”0},“scheduler:{“scheduler_interval:”1s”,“class_c:{“downlink slink_lock_duration:”2s”,“multicast_网关_delay:”2s:“2s”},“api:”Cert0.0:“cert:”0.8000:”tlu::::“0:0:”“,”tls_密钥“:”,”网关“:{”ca_证书“:”,”ca_密钥“:”,”客户机_证书生命周期“:”8760h0m0s“,”后端“:{”类型“:”mqtt“,”多下行链路_功能“:”混合“,”mqtt“:{”事件主题“:”网关/+/+/+//事件/+”,“命令主题_模板“:”网关/{.GatewayID}/command/{.CommandType}”,“服务器“:”tcp://localhost:1883,“用户名”:“密码”:”,“最大重新连接间隔”:“1m0s”,“qos”:0,“清理会话”:“true”,“客户端id”:“ca证书”:“tls证书”:“tls密钥”:“}”,amqp:{“url”:”amqp://guest:guest@localhost:5672,“事件队列名称”:“网关事件”,“事件路由密钥”:“网关。*.event.*”,“命令路由密钥模板”:“网关{.GatewayID}}.command.{.CommandType}},{.gcp_发布子”:{”凭据文件“:”项目id“:”上行链路主题名称“:”下行链路主题名称“:”上行链路保留时间“:”24h0m0s“}”,azure iot hub“:{”事件连接字符串“:{”值“:”可编辑“:”true“,”说明“:”此连接字符串必须指向iot hub将(上行链路)网关事件转发到的服务总线队列。“},”命令连接字符串:{“值”:“可编辑”:“真”,“描述”:“此连接字符串必须指向物联网集线器,并由ChirpStack网络服务器用于向网关发送命令。”}}},“监控”:{“绑定”:“prometheus_端点”:“假”,“prometheus_api_定时直方图”:“假”,“healthcheck_端点”:“假”},“加入服务器”:{“resolve_join_eui”:“false”,“resolve_domain_后缀”:“.joineuis.lora alliance.org”,“default”:{“server”:”http://localhost:8003“,”ca_cert:“,”tls_cert:“,”tls_key:“}}”,网络_controller:“{”服务器“,”ca_cert:“,”tls_cert:“,”tls_key:“}}”
运行上述代码时出现的错误是:

回溯(最近一次呼叫最后一次):
文件“”,第1行,在
toml_string=toml.dumps(数据)
文件“/usr/local/lib/python3.8/dist-packages/toml/encoder.py”,第67行,转储
提升值错误(“检测到循环参考”)
ValueError:检测到循环引用
深入研究后,我发现删除一个键值对后,代码工作正常。键值对是:

"type": "mqtt"
此键值对的位置是
数据[“网络服务器”][“网关”][“后端”]

我无法理解这种情况。 我试图更改键值对字符串,但仍然存在相同的问题。只有删除此键值对才能解决问题。但我需要此对


非常感谢您的帮助。提前谢谢。

我试图重现您的问题,因为我计划也从json配置切换到toml配置。我已经安装了
toml
0.10.1版

数据中有一个小问题(#在
“postgresql”
键后的注释),但该部分可以完全删除

我可以将示例最小化为:

data = { 
        "network_server":{
                "downlink_data_delay":{},
                "gateway":{"key3":{"key4":{}}
                }   
        }   
}

import toml
print(toml.dumps(data)) # ValueError: Circular reference detected
但奇怪的是,当你保留结构时,错误消失了,只是稍微重命名了键

只需从
“网络\u服务器”
中删除第一个“n”,您将获得na输出

那一定是一只虫子。非常可悲


更新:在查看源代码后,错误非常明显

retval = ""
if encoder is None:
    encoder = TomlEncoder(o.__class__)
addtoretval, sections = encoder.dump_sections(o, "")
retval += addtoretval
outer_objs = [id(o)]
while sections:
    section_ids = [id(section) for section in sections]
    for outer_obj in outer_objs:
        if outer_obj in section_ids:
            raise ValueError("Circular reference detected")
    outer_objs += section_ids
    newsections = encoder.get_empty_table()
    for section in sections:
        addtoretval, addtosections = encoder.dump_sections(
            sections[section], section)

        if addtoretval or (not addtoretval and not addtosections):
            if retval and retval[-2:] != "\n\n":
                retval += "\n"
            retval += "[" + section + "]\n"
            if addtoretval:
                retval += addtoretval
        for s in addtosections:
            newsections[section + "." + s] = addtosections[s]
    sections = newsections
return retval
或者不是吗?好的,它跟踪节的
id
s,但是在循环迭代之间节不会被保留。当
id
s被重用时,程序会被混淆

快速修复:在
dumps
函数中修补
toml/encoder.py
文件:

  • 在while循环之前添加
    allsections=[]

  • 在此处添加一行:

         allsections += sections   # <---
         sections = newsections
     return retval
    
    allsections+=节#