【发布时间】:2020-01-09 11:01:04
【问题描述】:
在字典中的python中,如果key是byte string,那么json.dumps会抛出错误,所以我试图将所有keys递归转换为string,然后再将它们传递给json.dumps。
Note: json.dumps converts the value to str using default function but not keys
以下是我的函数,它将检查任何byte string 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
我在 django 中调试一些代码
我想在我的代码的某个位置检查 request 对象
所以我有
request_dir = dir(request)
然后使用 keys_string 将任何字节键转换为字符串(否则 json 转储将引发错误)
request_dir_keys_stringed = keys_string(request_dir)
然后终于
json.dumps(request_dir_keys_stringed, indent=4, sort_keys=True, default=str)
当我尝试做 request_dir_keys_stringed = keys_string(request_dir) 它说
in keys_string
for k,v in d.items():
RuntimeError: dictionary changed size during iteration
我发现这种情况发生在:
k: user 和 v: <SimpleLazyObject: <User: test@gmail.com>>
我尝试了request.session 对象,它不会抛出这样的错误。但有些对象会。
request_session_dir = dir(request.session)
request_session_dir_keys_stringed = keys_string(request_session_dir)
json.dumps(request_session_dir_keys_stringed, indent=4, sort_keys=True, default=str)
遇到这种情况怎么办
重现问题的更多信息:
$ python --version
Python 3.7.3
$ django-admin --version
2.2.6
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')
实施解决方案后,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
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
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)
现在请求对象显示没有任何错误
【问题讨论】:
-
Python 和 Django 版本好吗? (无法在此处重现该问题)。
-
我已经在编辑的问题中添加了信息
-
dir(request)不总是返回list吗?所以你的代码永远不会到达for循环? -
有人真的可以用 OP 的代码重现这个问题吗?
dir()返回一个字符串列表,所以我看不到它如何进入for k,v in d.items()部分。 @SanthoshYedidi 您发布的代码不是实际引发此错误的代码,或者内置的dir函数此时被其他东西所掩盖。请在函数的开头添加print(dir)并发布它打印的内容。 -
是的,可以是列表,但是列表可以是对象的集合。像 [ 'someitem,[{},{}],{},etc] 所以第一次它可能不会进入循环,但当更深入时它应该
标签: python django dictionary