使用pyyaml读取目录中的多个文件

Reading multiple files in a directory with pyyaml

我正在尝试读取目录中的所有 yaml 文件,但我遇到了问题。首先,因为我使用的是 Python 2.7(而且我不能更改为 3)并且我所有的文件都是 utf-8(我也需要它们保持这种方式)。

import os
import yaml
import codecs


def yaml_reader(filepath):
    with codecs.open(filepath, "r", encoding='utf-8') as file_descriptor:
        data = yaml.load_all(file_descriptor)
        return data

def yaml_dump(filepath, data):
    with open(filepath, 'w') as file_descriptor:
        yaml.dump(data, file_descriptor)

if __name__ == "__main__":
    filepath = os.listdir(os.getcwd())
    data = yaml_reader(filepath)
    print data

当我 运行 此代码时,python 给我消息:

TypeError: coercing to Unicode: need string or buffer, list found.

我想让这个程序显示文件的内容。谁能帮帮我?

我想问题出在文件路径上。 os.listdir(os.getcwd()) returns 目录中所有文件的列表。所以您将列表传递给 codecs.open() 而不是文件名

你的代码有多个问题,除了它是无效的 Python,你格式化它的方式。

def yaml_reader(filepath):
    with codecs.open(filepath, "r", encoding='utf-8') as file_descriptor:
        data = yaml.load_all(file_descriptor)
        return data

但是没有必要进行解码,PyYAML 完全能够处理 UTF-8:

def yaml_reader(filepath):
    with open(filepath, "rb") as file_descriptor:
        data = yaml.load_all(file_descriptor)
        return data

我希望您意识到您尝试加载多个文档并始终在 data 中得到一个列表,即使您的文件包含一个文档。

然后是行:

       filepath = os.listdir(os.getcwd())

给你一个文件列表,所以你需要做:

       filepath = os.listdir(os.getcwd())[0]

或以其他方式决定要打开哪些文件。如果你想将所有文件(假设它们是 YAML)合并到一个大的 YAML 文件中,你需要做:

if __name__ == "__main__":
    data = []
    for filepath in os.listdir(os.getcwd()):
        data.extend(yaml_reader(filepath))
    print data

并且您的转储​​例程需要更改为:

def yaml_dump(filepath, data):
    with open(filepath, 'wb') as file_descriptor:
        yaml.dump(data, file_descriptor, allow_unicode=True, encoding='utf-8')

然而,这一切都会给您带来最大的问题:您正在使用 PyYAML,它会破坏您的 YAML,删除 flow-style、注释、锚点名称、特殊 int/float、标量周围的引号等. 除此之外,PyYAML 尚未更新以支持 YAML 1.2 文档(自 2009 年以来一直是标准)。我建议您改用 ruamel.yaml(免责声明:我是该软件包的作者),它支持 YAML 1.2 并保留注释等。

即使您必须使用 Python 2,您也应该使用 Python 3 之类的语法,例如对于 print,您可以通过 from __future__ 导入获得。

所以我建议你这样做:

pip install pathlib2 ruamel.yaml

然后使用:

from __future__ import absolute_import, unicode_literals, print_function

from pathlib import Path
from ruamel.yaml import YAML

if __name__ == "__main__":
    data = []
    yaml = YAML()
    yaml.preserve_quotes = True
    for filepath in Path('.').glob('*.yaml'):
        data.extend(yaml.load_all(filepath))
    print(data)
    yaml.dump(data, Path('your_output.yaml'))