【问题标题】:Yaml : Found unexpected end of streamYaml:发现流的意外结束
【发布时间】:2018-01-14 15:36:54
【问题描述】:

我编写了一个 python 代码来生成一个 YAML 文件(称为targets.yml),该文件由一个名为 prometheus 的流行监控应用程序读取。 prometheus 成功读取了 YAML 文件及其内容,但它也会在日志中引发错误,如下所示。

level=error msg="Error reading file "/var/targets/targets.yml": yaml: 
line 218: found unexpected end of stream" source="file.go:199" 

我无法摆脱这个错误,尽管我适当地关闭了 YAML 文件,下面是它的代码:-

while True:

    create()
    with open('/var/targets/targets.yml', 'w') as output:
        print "opened the file to write"
        i=0
        for item in result:
            if(item != None and item['status'] == "ACTIVE"):
               print item['domains']['partner']
               print item['status']
               output.write("\n\n")
               output.write("- targets: ['" + "https://" + item["domains"]["agency"] + "']\n")
               output.write("  labels:\n")
               output.write("    alias: " + item["alias"])
               foo=item["name"]
           #print foo
               if isinstance(foo,basestring):
                  foo=foo.encode('utf8')
               else:
                  foo=unicode(foo).encode('utf8')
output.close()
print("Waiting for 300 seconds, before relooping")
time.sleep(100)

我也不认为我的文件扩展名有什么不同。有人可以建议吗?

【问题讨论】:

  • prometheus 期望文件的结构如何?你需要单独的 yaml 文件吗?这些用 --- 或 ... 划定(我不记得了)。您是否可能需要附加到文件而不是覆盖它?
  • @PhilipStark 我想我编写 yaml 文件的方式应该没问题,因为如果它不是普罗米修斯预期的,它会给我一个错误写掉。相反,它会以随机间隔抛出一个错误,我想知道它是否与refresh interval(默认值为 300 秒)和每 100 秒后我的应用程序生成 yaml 文件有关(如上面的应用程序代码)。请注意,在我的情况下,我必须覆盖该文件。
  • 那么我真的建议你使用 pyyaml 模块来构建你的 yaml 文档。在某些情况下,您可能会遇到 yaml 语法错误。 item["alias"] 或 item["domains"]["agency"] 的可能值是什么?
  • @PhilipStark item[alias] 只是一个类似 "example" 的字符串,而 item["domains"]["agency"] 也是一个类似 "ui.xyz.abc.net" 的字符串。就像你说的,也许 pyyaml 是一个更好的选择。

标签: python python-2.7 python-3.x yaml prometheus


【解决方案1】:

在我的情况下,引号" 的打开和关闭之间存在不匹配, 但错误在另一个地方,然后是错误报告的行。

【讨论】:

    【解决方案2】:

    编辑:正如 brian-brazil 指出的那样,这不会修复问题,但它可能会缓解症状。因此,仅当您绝对无法实施 brian-brazil 的答案时才应用此答案。

    详细说明brian-brazil's 回答:此操作不是原子的事实意味着其他进程(对您的python脚本一无所知)可以在完成写入之前读取您的YAML文件。

    如果直接写入该文件非常重要,您可能需要禁用缓冲(doc) 并立即写入整个 YAML 文档。为此,您可以将当前正在单独执行的所有“写入”收集到一个字符串中,然后一次写入所有内容。

    而不是

    output.write("\n\n")
    output.write("- targets: ['" + "https://" + item["domains"]["agency"] + "']\n")
    output.write("  labels:\n")
    output.write("    alias: " + item["alias"])
    

    你会做这样的事情:

    yaml = ""
    yaml += "\n\n"
    yaml += "- targets: ['" + "https://" + item["domains"]["agency"] + "']\n"
    yaml += "  labels:\n"
    yaml += "    alias: " + item["alias"]
    output.write(yaml)
    

    这不是最有效的方法,但为了便于说明,应该没问题。

    【讨论】:

    • 这并没有什么区别,写一个文件然后rename是这样做的。
    • 我认为这会减轻问题的节奏,但不会彻底解决问题。这就是为什么我将其指定为直接写入文件是否重要的​​解决方案。
    • 我添加了免责声明。
    • @philip Stark 不幸的是,就像我在 brian-brazil 的回答中提到的那样,没有一个建议能够解决这个问题。
    【解决方案3】:
    with open('/var/targets/targets.yml', 'w') as output:
    

    这是你的问题的一部分,这不是原子的。您需要创建一个临时文件,然后将其移动到位。

    我还建议使用 yaml 库而不是手动创建它。

    【讨论】:

    • 很抱歉,请您澄清一下“然后将其移动到位。”。我没有得到你的这部分答案。
    • 将 yaml 写入临时文件(例如 /tmp/temporary-targets.yml),然后将该文件移动到 /var/targets/targets.yml
    • @brian-brazil 不幸的是,这仍然不能解决问题。我在 prometheus 配置的file_sd_config 中使用这个文件,运行生成这个文件的应用程序作为一个边车容器以及一个 pod 中的 prometheus。我还尝试检查 refresh interval 是否会导致此问题,因为在我的应用程序代码中,我每 300 秒循环一次。但也无法从这里弄清楚任何事情。
    猜你喜欢
    • 2015-11-17
    • 1970-01-01
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-23
    • 2020-08-17
    相关资源
    最近更新 更多