gpt4 book ai didi

python - 使用 str.format_map() 时超出最大字符串递归

转载 作者:行者123 更新时间:2023-11-30 22:43:33 24 4
gpt4 key购买 nike

我正在使用str.format_map格式化一些字符串,但当该字符串包含引号(甚至转义)时我遇到问题。这是代码:

class __FormatDict(dict):
def __missing__(self, key):
return '{' + key + '}'

def format_dict(node, template_values):
template_values = __FormatDict(template_values)
for key, item in node.items():
if isinstance(item, str):
node[key] = item.format_map(template_values)

对于常规字符串(不包含括号或引号),它可以工作,但是对于像 "{\"libraries\":[{\"file\":\"bonjour.so\",\"modules\":[{\"name\":\"hello\"}]}]}" 它崩溃,并显示消息 ValueError: Max string recursion超过

在格式化之前使用 json.dumps(item) 对引号进行转义并不能解决问题。应该采取什么措施来解决这个问题?我正在修改从 JSON 文件获取的字符串,并且我更愿意修复 Python 代码,而不是更新我使用的 JSON 文档。

最佳答案

您不能对 JSON 数据使用 __missing__ 技巧。存在多个问题。这是因为 {...} 替换字段中的文本不仅仅被视为字符串。看看the syntax grammar :

replacement_field ::=  "{" [field_name] ["!" conversion] [":" format_spec] "}"
field_name ::= arg_name ("." attribute_name | "[" element_index "]")*

在替换字段中,!...:... 也有意义!这些部分的内容也有严格的限制。

递归错误来自占位符内占位符内的多个嵌套{...}占位符; str.format()str.format_map() 无法支持大量嵌套:

>>> '{foo:{baz: {ham}}}'.format_map({'foo': 'bar', 'baz': 's', 'ham': 's'})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Max string recursion exceeded

但是这里还有其他问题:

  • : 冒号表示 formatting specification ,然后从 : 之前的部分传递给对象(键)。如果您想恢复这些值,则必须为 __missing__ 返回值提供一个带有 __format__ 方法的包装对象。

  • 其中包含 .[...] 的字段名称也有特殊含义; "bonjour.so" 将被解析为 "bonjour 键,带有 so 属性。[...] 同上 在字段名称中,但用于项目查找。

最后两个可以通过使用 __format____getitem____getattr__ 方法返回包装对象来接近,但仅限于有限的情况:

>>> class FormatWrapper:
... def __init__(self, v):
... self.v = v
... def __format__(self, spec):
... return '{{{}{}}}'.format(self.v, (':' + spec) if spec else '')
... def __getitem__(self, key):
... return FormatWrapper('{}[{}]'.format(self.v, key))
... def __getattr__(self, attr):
... return FormatWrapper('{}.{}'.format(self.v, attr))
...
>>> class MissingDict(dict):
... def __missing__(self, key):
... return FormatWrapper(key)
...
>>> '{"foo.com": "bar[baz]", "ham": "eggs"}'.format_map(MissingDict())
'{"foo.com": "bar[baz]", "ham": "eggs"}'
>>> '{"foo .com": "bar [ baz ]", "ham": "eggs"}'.format_map(MissingDict())
'{"foo .com": "bar [ baz ]", "ham": "eggs"}'

这对于“空”属性失败:

>>> '{"foo...com": "bar[baz]", "ham": "eggs"}'.format_map(MissingDict())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Empty attribute in format string

简而言之,该格式对 {...} 大括号内包含的内容做出了太多假设,JSON 数据的假设很容易被破坏。

我建议您查看使用string.Template() class相反,一个更简单的可以子类化的模板系统;默认是查找并替换 $identifier 字符串。 Template.safe_substitute() method完全按照您的意愿行事;替换已知的 $identifier 占位符,但保留未知名称不变。

关于python - 使用 str.format_map() 时超出最大字符串递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41738604/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com