【问题标题】:How do I properly output a string for a YAML file that includes a "#"?如何正确输出包含“#”的 YAML 文件的字符串?
【发布时间】:2020-10-16 12:13:01
【问题描述】:

我正在使用 Django 3 和 Python 3.7。我正在尝试编写一个函数来输出格式正确的 YAML。我有这个...

def strip_invalid(s):
    res = ''
    for x in s:
        if Reader.NON_PRINTABLE.match(x):
            # res += '\\x{:x}'.format(ord(x))
            continue
        res += x
    return res
...
yaml_street = load(strip_invalid(street.strip().encode("utf-8", 'ignore').decode("utf-8")))

问题是,如果“street”是“55 E JACKSON BLVD # 150”,则上述输出

55 E JACKSON BLVD

请注意,包括“#”在内的所有内容均已删除。如何调整上述内容以包含所有内容,但可能为 YAML 输出正确转义?

【问题讨论】:

  • 向我们展示 YAML。
  • 什么是loadstrip_invalid 应该产生什么,一个文件名,一个有效的 YAML 字符串?
  • @chepner,是的,该函数应该生成一个有效的 YAML 字符串,删除所有非 UTF-8 字符(或至少使所有字符 UTF-8 安全)
  • 对不起,如果我在这里“大声”思考:从您下面的评论看来,您要么有 XY problem,您对 yaml.load 所做的事情的误解导致您写下整个strip_invalid 函数首先不应该出现。 要么您将此作为您自己对 YAML 理解的练习/挑战,然后您可能应该向我们提供 load 函数的来源及其代码(如果您自己编写)。
  • 也许你可以通过解释你自己对yaml = load('sting')在这里做什么的理解来澄清这一点。

标签: python python-3.x django utf-8 yaml


【解决方案1】:

您可能打算使用dump 而不是load

dump(data, stream=None) 将给定的 Python 对象序列化到流中。如果 stream 为 None,则返回生成的流。

来源:https://pyyaml.org/wiki/PyYAMLDocumentation#reference

from yaml import dump
print(dump({'foo': 'bar # with hash'}))

输出:

foo: 'bar # with hash'

所以你的整个代码最终会是:

from yaml import dump
street = '  55 E JACKSON BLVD # 150  '
yaml_street = dump(street.strip())
print(yaml_street)

输出:

'55 E JACKSON BLVD # 150'


但是,如果您坚持编写自己的函数,则会发生这种情况,因为哈希 # 实际上是 YAML 中的注释

foo: I am a string until the hash # and then I am a comment

为避免这种情况,您可以quote your string:

foo: 'I am a string until the second quote # even if there is a hash'

另请注意,在 YAML 中转义现有引用 ' 只是将其翻倍。

foo: 'Don't us me I am a broken YAML construct'

将被解决

foo: 'I''m able to fit quote in a YAML string by doubling it'

所以你可以去:

def strip_invalid(s):
    res = ''
    for x in s:
        if Reader.NON_PRINTABLE.match(x):
            # res += '\\x{:x}'.format(ord(x))
            continue
        res += x
    return "'{}'".format(res.replace("'","''"))

yaml_street = strip_invalid(street.strip().encode("utf-8", 'ignore').decode("utf-8"))

【讨论】:

  • 谢谢 - 我尝试了您的第二个解决方案并遇到了问题。如果我的字符串是'41°47'49"N 87°35'29"W',代码'load(Command.strip_invalid(row['address'].strip().encode("utf-8", ' ignore').decode("utf-8")))' 因错误而死,“yaml.parser.ParserError: expected '', but found '', in "" , 第 1 行, 第 20 列:, '4''1''°''4''7'''''4''9''"''N'' ''8''7''°'' 3''5'''' ..."。
  • 因为你一直在使用load,而你应该使用dumpload 获取一个 stream,您可以从中读取 YAML 文档并对其进行解码。
  • 正如@chepner load 指出的那样,可能是您问题的一部分。也就是说,在 YAML 中转义引号意味着将其翻倍。
  • 出于某种原因,我认为您的解决方案中有“负载”。无论如何,我用“dump”替换了“load”,并将 strip_invalid 更改为你所拥有的,但它仍然产生奇怪的输出。例如,“222 W. Merchandise Mart Plaza”被翻译成以“'''2''''2''''2''''''''W''''开头的东西。'' '' ''''M''''e''''r''''c''''h''''a''''n''''d''''i''' 's'''e'''' ..."
  • 但实际上,@Dave 根本不应该有那个函数 dump() 会处理那些假定的无效字符。
猜你喜欢
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 2011-01-17
  • 1970-01-01
  • 2016-04-23
相关资源
最近更新 更多