17

dbにいくつかのレコードを作成するyaml設定ファイルがあります:

setting1:
  name: [item,item]
  name1: text
anothersetting2:
  name: [item,item]
  sub_setting:
      name :[item,item]

このファイルをsetting3で更新し、次の方法でdbのレコードを再生成する場合:

import yaml
fh = open('setting.txt', 'r')
setting_list = yaml.load(fh)
for i in setting_list:
    add_to_db[i]

それらの設定の順序(db内のid番号)は、imがdbに追加するたびに同じままであることが重要です...そしてsetting3はyaml.load()の末尾に追加されるだけなので、そのidは' tすでにdbにあるレコードを混乱させます...現時点では、別の設定を追加してyaml.load()を呼び出すたびに、レコードが異なる順序でロードされ、異なるIDになります。私はどんなアイデアも歓迎します;)

編集: 私はabarnertのヒントに従い、この要点を理解しましたhttps://gist.github.com/844388

期待通りに動作します!

4

5 に答える 5

16

私のプロジェクトoyamlはPyYAMLのドロップイン代替品であり、collections.OrderedDict通常のdictの代わりにマップをロードします。それをpipインストールして通常どおりに使用するだけです-Python3とPython2の両方で動作します。

あなたの例でデモ:

>>> import oyaml as yaml  # pip install oyaml
>>> yaml.load('''setting1:
...   name: [item,item]
...   name1: text
... anothersetting2:
...   name: [item,item]
...   sub_setting:
...       name :[item,item]''')
OrderedDict([('setting1',
              OrderedDict([('name', ['item', 'item']), ('name1', 'text')])),
             ('anothersetting2',
              OrderedDict([('name', ['item', 'item']),
                           ('sub_setting', 'name :[item,item]')]))])

stdlib dictが順序を保持している場合(Python> = 3.7、CPython> = 3.6)oyaml、通常のdictを使用することに注意してください。

于 2018-05-09T15:44:53.200 に答える
5

これでruaml.yamlを使用できるようになりました。

https://pypi.python.org/pypi/ruamel.yamlから:

ruamel.yamlは、コメントのラウンドトリップ保存、seq / mapフロースタイル、およびマップキーの順序をサポートするYAMLパーサー/エミッターです。

于 2016-08-18T10:49:08.170 に答える
4

YAML仕様では、マッピング内のキーの順序は信頼できない「表現の詳細」であると明確に述べられています。したがって、マッピングに依存している場合、設定ファイルはすでに無効になっています。可能であれば、有効なYAMLを使用することをお勧めします。

もちろん、YAMLは拡張可能であり、設定ファイルに「順序付きマッピング」タイプを追加することを妨げるものは何もありません。例えば:

!omap setting1:
  name: [item,item]
  name1: text
!omap anothersetting2:
  name: [item,item]
  !omap sub_setting:
      name :[item,item]

yaml使用しているモジュールについては言及していません。標準ライブラリにはそのようなモジュールはなく、その名前のモジュールを提供するPyPIだけに少なくとも2つのパッケージがあります。ただし、私が知る限り、これが最も人気があるため、PyYAMLだと推測します。

上記の拡張機能は、PyYAMLを使用して簡単に解析できます。http://pyyaml.org/ticket/29を参照してください:

def omap_constructor(loader, node):
    return loader.construct_pairs(node)
yaml.add_constructor(u'!omap', omap_constructor)

今、代わりに:

{'anothersetting2': {'name': ['item', 'item'],
  'sub_setting': 'name :[item,item]'},
 'setting1': {'name': ['item', 'item'], 'name1': 'text'}}

あなたはこれを得るでしょう:

(('anothersetting2', (('name', ['item', 'item']),
  ('sub_setting', ('name, [item,item]'),))),
 ('setting1', (('name', ['item', 'item']), ('name1', 'text'))))

もちろん、これによりtupleKey-Valuetupleが得られますが、construct_ordereddictを簡単に記述して、OrderedDict代わりに取得できます。入力だけでなく出力も必要な場合は、OrdereredDictオブジェクトをsとして格納するリネータを作成することもできます。!omap

本当にPyYAMLをフックして、デフォルトのマッピングのOrderedDict代わりにを使用するようdictにしたい場合、パーサーオブジェクトを直接操作している場合は非常に簡単ですが、高レベルの便利なメソッドを使い続けたい場合はさらに困難です。 。幸い、上記のリンクされたチケットには、使用できる実装があります。実際のYAMLを使用しているのではなく、バリアントを使用していることを覚えておいてください。そのため、ファイルを処理する他のソフトウェアは破損する可能性があり、おそらく破損する可能性があります。

于 2012-11-08T22:30:27.713 に答える
0

順序付けされた辞書であることがわかっている特定の単一アイテムについて、リストのアイテムを作成し、コレクションを使用します。OrderedDict:

setting1:
  - name: [item,item]
  - name1: text
anothersetting2:
  - name: [item,item]
  - sub_setting:
      name :[item,item]

import collections
import yaml
fh = open('setting.txt', 'r')
setting_list = yaml.load(fh)

setting1 = collections.OrderedDict(list(x.items())[0] for x in setting_list['setting1'])
于 2017-07-28T00:56:53.117 に答える
-2

最後に聞いたところによると、PyYAMLはこれをサポートしていませんでしたが、辞書または辞書のようなオブジェクトを開始点として受け入れるように変更するのはおそらく簡単でしょう。

于 2012-11-08T22:08:57.000 に答える