【问题标题】:I don't like how "yaml.dump()" saves its files. Is there an alternative?我不喜欢“yaml.dump()”如何保存它的文件。有替代方案吗?
【发布时间】:2011-04-01 12:59:08
【问题描述】:

我最近发现了 YAML,结果证明它是我项目的绝佳格式(我正在创建一个基于文本的 RPG)。它完美地处理了我需要的一切——区域文件(带有 desc、出口、objs、npcs 等的房间)、脚本文件、npc 文件、目标文件……它可以解决所有问题!只有一件事......

当更新这些文件中的值时,我当然需要将它们写回磁盘以保留更改。不幸的是,YAML 的dump() 方法确实把事情搞得一团糟。首先它将所有键按字母顺序排列,然后似乎每行放置一对 k:v。这有效地将一个 5 行的文件变成了 94 行。

我尝试使用 write() 将 YAML 对象写回磁盘,但它抛出了

TypeError: 需要一个字符缓冲区对象

在我身上。 Pickle 会保存它,但我认为这会破坏数据的 YAML 特性。在没有dump() 的情况下,有没有保存 YAML 对象的好方法?我听说过 SQLite,它会和 YAML 一样工作吗?我几乎没有数据库经验,但似乎 YAML 对象基本上是数据库。是否值得重新编码所有内容以使用 SQLite?与我现在遇到的问题不同,用它保存更改的值是否容易?

这里的任何帮助都会很棒。我非常喜欢 YAML。我挣扎了很长时间,试图找到一种方法来存储我的游戏所需的所有数据,当我找到 YAML 时,它就像天使合唱团在它上面唱着他们的荣耀时发出圣光一样——所以你可以理解如果我首先想知道一种不使用dump() 将 YAML 数据保存到磁盘的方法。如果没有,欢迎提出建议!

【问题讨论】:

    标签: python save yaml


    【解决方案1】:

    YAML 是一种在 Python 和文本可编辑格式之间序列化和反序列化字典和列表的方法。它不适合存储丰富的数据、多用户访问、快速查找数据、保证数据完整性以及使数据库成为数据库的所有其他事情。

    您将 YAML 用作数据库,但它不是数据库。例如,键的重新排序是key: value 对被表示为 Python 字典这一事实的人工产物,它本质上是无序的。

    您肯定需要花一些时间来学习一些有关数据库的知识。

    SQLite 是一个很好的起点。您还可以查看 Postgres 或 MySQL。您可能需要阅读一些 SQL 初学者指南以及使用 Python 进行数据库访问。网上有很多。

    【讨论】:

    • 然而,这不是问题所在。 YAML 非常适合以人类可读的格式存储数据。一旦你加载它,你就拥有了原生 Python 数据结构,因此访问速度比任何数据库实际提供的都要快,但会以内存为代价。当数据不能一次在内存中时,数据库获胜,是的。
    • 我查看了几个关于 Python 中 SQLite 的视频,看起来走这条路会有很多东西要学。我唯一的问题是它可能会暂时停止我的进步。但是,它似乎可能比简单地访问 2d 字典对象更强大。与 YAML 相比,数据库会慢多少?如果说我在数据库中绘制了一个区域,其中每一行包含该区域中 1 个房间所需的所有数据,并且有 50 个房间,那真的会那么慢吗?
    • 数据库通常应该比 YAML 更快,因为涉及的字符串处理会更少(但这取决于您设计数据库结构的程度)
    • @drew, Re.速度,正如 delnan 所说,一旦 YAML 被解析,它就全部在内存中,这是超快的。如果您只有 50 个房间,那么毫无疑问,一次将其全部保存在内存中是合理的。如果您还不想了解数据库,并且 YAML 不适合您,那么为什么不将您的房间表示为对象并将它们作为泡菜保存到磁盘呢?您可以编写一个导入脚本,从文本文件、YAML 文件或 CSV 文件中获取房间定义,然后从这些文件中创建对象,并在保存操作时将它们腌制。
    • 这听起来不错,尽管在谈到 OOP 时我仍然有点耳后。也就是说,我确实希望能够尽可能多地结合 OOP。我觉得不这样做是不负责任的……虽然我不确定这是否是一个好的心态。不过,我想我理解您将房间表示为对象的建议,并且会试一试。最终我关于如何保存文件的问题可能必须通过创建一个编辑器而不是直接编辑文件来解决——这就是我遇到的问题(并且会在 Pickle 中遇到)。
    【解决方案2】:

    可以使用 YAML 和 Python 保持顺序。

    Python 有 OrderedDict,而 YAML 有一个等效的有序映射,称为 omap

    不幸的是,当您使用 YAML 转储 OrderedDict 时,它会尝试保留 OrderedDict python 对象类型,而不是将其转换为 YAML omap。这部分是因为 YAML 规范旨在与多种语言配合使用,从技术上讲,我相信 YAML 映射或 omap 允许重复键(我必须重新研究,但我看到它被引用为YAML 和 JSON 之间的“关键”区别——YAML 声明了它如何处理 JSON 没有的重复密钥。)

    无论如何,有一种方法可以告诉 YAML 将数据加载到 OrderedDict 中,并将 OrderedDict 顺序转储到 map 或 omap 中。我找到的最简洁的来源是py-lessly。尽管网络上还有其他一些实现。我也喜欢 py-less 代码转储到一个简单的 yaml 映射,它不需要 !!omap 在每个字典旁边 - 保持 YAML 漂亮!

    还有 layered-yaml-attrdict-config 将 YAML 数据加载到一个名为 AttrDict 的 OrderedDict 子类中,并具有一些附加功能。我必须在这个实现中添加一些东西才能为我工作——我认为它在转储时丢失了顺序,所以我从 py-less 实现中添加了代码。我还想使用组合的 dict 和列表结构,并且不得不编写一些额外的代码来递归地将 AttrDict 应用于整个数据结构。

    从这些示例中,您可以了解如何使用 YAML 处理有序映射。我目前正在为我希望保持相对可读且顺序很重要的应用程序设置实现此功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-17
      • 1970-01-01
      • 2020-06-25
      • 1970-01-01
      相关资源
      最近更新 更多