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

遍历Django请求对象遇字典迭代大小变更错误及字节键转换

解决Python字典字节键转字符串及Django request对象迭代报错问题

背景问题

在Python里,当我们用json.dumps序列化带有字节字符串键的字典时会直接报错——因为json.dumps的default参数只能处理值的转换,完全不会处理字典的键。为了搞定这个问题,我们通常会写一个递归函数keys_string,把所有字节类型的键解码成字符串,同时递归处理嵌套的容器(字典、列表、元组、集合)。

最初的实现代码

def keys_string(d):
    rval = {}
    if not isinstance(d, dict):
        if isinstance(d,(tuple,list,set)):
            v = [keys_string(x) for x in d]
            return v
        else:
            return d
    for k,v in d.items():
        if isinstance(k,bytes):
            k = k.decode()
        if isinstance(v,dict):
            v = keys_string(v)
        elif isinstance(v,(tuple,list,set)):
            v = [keys_string(x) for x in v]
        rval[k] = v
    return rval

遇到的RuntimeError问题

在Python 3.7.3 + Django 2.2.6的调试场景中,当我们尝试处理request对象时:

def articles(request):
    request_dir = dir(request)
    request_dir_keys_stringed = keys_string(request_dir)
    print(json.dumps(request_dir_keys_stringed, indent=4, sort_keys=True, default=str))
    return render(request, 'articles/main_page/articles.html')

触发了RuntimeError: dictionary changed size during iteration错误,具体是处理键user对应的SimpleLazyObject时出现的,但处理request.session时没有这个问题。

报错原因分析

这是因为直接迭代d.items()或者d.keys()时,如果迭代过程中原字典的大小发生了变化(比如Django的一些惰性对象在访问时会动态生成新的键),就会触发这个错误。而把d.keys()转换成列表list(d.keys())后,会先把所有键一次性加载到内存中,后续迭代的是这个固定的列表,不会受原字典动态变化的影响。

修复后的函数实现

def keys_string(d):
    rval = {}
    if not isinstance(d, dict):
        if isinstance(d,(tuple,list,set)):
            v = [keys_string(x) for x in d]
            return v
        else:
            return d
    # 先把键转为列表,避免迭代时原字典动态变化导致报错
    keys = list(d.keys())
    for k in keys:
        v = d[k]
        if isinstance(k,bytes):
            k = k.decode()
        if isinstance(v,dict):
            v = keys_string(v)
        elif isinstance(v,(tuple,list,set)):
            v = [keys_string(x) for x in v]
        rval[k] = v
    return rval

效果验证

修改后的函数可以正常转换Django的request对象,并且成功执行json.dumps序列化,不会再出现RuntimeError。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 09:07:27