簡體   English   中英

YAML output python 的格式

[英]YAML output format of python

我用PyYaml來 output 一個YAML文件。 但它重新訂購我的物品。 喜歡關注

>>> yaml.dump({'3':5, '1':3})
"{'1': 3, '3': 5}\n"

我想得到"{'3': 5, '1': 3}\n" 我可以做那件事嗎

附言 我試過collections.OrderedDict 它的 output 不好。 喜歡關注

>>> a= collections.OrderedDict()
>>> a['3']=1
>>> a['1']=2
>>> a['5']=2
>>> yaml.dump(a)
"!!python/object/apply:collections.OrderedDict\n- - ['3', 1]\n  - ['1', 2]\n  - ['5', 2]\n"

TL; DR:解決方案在兩行中注釋為“ LOOK HERE!”。 可能的,如果你接受的輸出將是列表的列表來處理YAML作為你的程序中,並與存儲的文件/文本排序類型的字典。

如果您不介意!! python / ordered_dict或!! omap這樣令人討厭的顯式類型,那么您也可以采用這種方式。 我的投票投給!! omap,但是我不確定有多少工具/庫支持它(我敢肯定,支持!! python / ordered_dict的工具會更少)。 最終,您要處理兩個獨立的數據集:dict本身和定義鍵順序的元數據。

(在YAML中有半魔術的方法可以強制有序的dict到處沒有!! python / ordered_dict或!! omap混亂,但是它們很脆弱,與字典的定義相矛盾,並且可能隨着基礎YAML庫的發展而中斷。順便說一下,這種情況對於JSON來說是相同的,因為YAML是JSON的超集,並且都不保證鍵的順序-這意味着解決方法第一次打破了符合標准的工具/用戶將文件弄亂的情況。)

這篇文章的其余部分是示例/驗證代碼,並解釋了為什么這種方式。

from __future__ import print_function
import yaml

# Setting up some example data
d = {'name': 'A Project',
     'version': {'major': 1, 'minor': 4, 'patch': 2},
     'add-ons': ['foo', 'bar', 'baz']}

# LOOK HERE!
ordering = ['name', 'version', 'add-ons', 'papayas']
ordered_set = [[x, d[x]] for x in ordering if x in d.keys()]
# In the event you only care about a few keys,
# you can tack the unspecified ones onto the end
# Note that 'papayas' isn't a key. You can establish an ordering that
# includes optional keys by using 'if' as a guard in the list comprehension.

# Demonstration
things = {'unordered.yaml': d, 'ordered.yaml': ordered_set}
for k in things:
    f = open(k, 'w')
    f.write(yaml.dump(things[k], default_flow_style=False, allow_unicode=True))
    f.close()

# Let's check the result
output = []
for k in things:
    f = open(k, 'r')
    output.append(dict(yaml.load(f.read())))
    f.close()

# Should print 'OK'
if output[0] == output[1]:
    print('OK')
else:
    print('Something is wrong')

創建的文件如下所示:

ordered.yaml:

- - name
  - A Project
- - version
  - major: 1
    minor: 4
    patch: 2
- - add-ons
  - - foo
    - bar
    - baz

unordered.yaml:

add-ons:
- foo
- bar
- baz
name: A Project
version:
  major: 1
  minor: 4
  patch: 2

這不會像您希望的那樣生成漂亮的YAML文檔。 就是說,它可以將漂亮的YAML作為初始輸入(是的!),並將腳本從不漂亮的,有序的YAML轉換為漂亮的,仍然有序的,字典式的YAML腳本非常簡單(我留給您練習) 。

如果您要保留的鍵排序,請將其寫入有序列表/元組。 使用該列表生成列表的有序列表(不過,不是元組列表,因為在YAML中會得到!! python / tuple類型,這很糟糕)。 將其轉儲到YAML。 要按正常方式讀回它,然后將該結構傳遞給dict(),您將返回到最初使用的原始字典。 如果您有一個嵌套結構要求保留其順序,則可能必須遞歸地遞減該結構(在代碼中比在散文中解釋要容易得多(這可能已經知道)。

在此示例中,我想讓項目“名稱”首先出現在文件中,然后是“版本”數字元素,然后是“附加組件”。 通常,當您調用dump()時,PyYAML會按字母數字順序對字典鍵進行排序,但這是不可靠的,因為將來可能會發生變化,並且YAML標准中沒有要求這樣做的鍵,因此我無法保證使用其他YAML實用程序將以這種方式做事。 “附加組件”位於“名稱”之前,因此我有訂購問題。 因此,我定義了我的訂單,然后打包一個有序列表列表,然后將其轉儲。

您要從本質上無序的訂單中要求訂單。 字典是一個哈希表,在內部專門按搜索速度排序。 該順序是您不應該弄亂的,因為如果明天發現一種更快的實現字典的方式,則運行時需要在不破壞依賴於字典作為哈希表的有用抽象的每個人的代碼的情況下實現它。

同樣,YAML不是標記語言(畢竟,它最初是“ Yaml不是標記語言”的縮寫),它是一種數據格式。 區別很重要。 一些數據是有序的,例如元組和列表。 有些則不是,例如成袋的鍵/值對(與哈希表稍有不同,但概念上相似)。

我使用這種解決方案的遞歸版本來保證跨不同YAML實現的YAML輸出,而不是為了人類可讀性,而是因為我在YAML中傳遞了大量數據,並且每條記錄都必須用鍵進行簽名,並且不確定的順序可以防止使用字典/哈希時使用統一的簽名。

YAML映射是無序的,Python字典也是如此。 讀取文件並保持排序的官方方式是使用!!omap但是那些在PyYAML中被轉換為元組,並且不像dict / ordereddict / OrderedDict那樣容易更新。

如果您已經有一個讀入並更新的yaml文件,則可以使用我的ruamel.yaml庫,該庫在來回模式下按ordersdict讀取映射,並將其寫為普通映射(它還會保留注釋)。

給出了用法示例 ,作為對另一個問題的解答。

I might be a little late to the party but using the function add_representer of the yaml package seems to resolve the problem.I just added the yaml.add_representer(collections.OrderedDict, Representer.represent_dict) before my yaml.dump and my yaml does not不再有上述格式警告:

import collections
import yaml

l= collections.OrderedDict()
l['hax']=45
l['ko']=[4,5]
l['ax']="less"

yaml.dump(l)
#output:'!!python/object/apply:collections.OrderedDict\n- - - hax\n    - 45\n  - - ko\n    - - 4\n      - 5\n  - - ax\n    - less\n'

#adding a representer for Ordered Dictionaries
from yaml.representer import Representer
yaml.add_representer(collections.OrderedDict, Representer.represent_dict)

yaml.dump(l)
#output'ax: less\nhax: 45\nko:\n- 4\n- 5\n'

如果有幫助,請告訴我。

另一種解決方案可能也是使用oyaml而不是 pyyaml,正如它在這篇文章中所建議的那樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM