pyyamlでハマったこと


やりたかったこと

数値計算したデータを保存する時、二次元データならcsvでこと足りるが、dict型などのもっと複雑な構造を持ったデータをまとめて保存したいことがある。pickleを使う方法もあるが、pickleで保存してしまうとpythonを経由しないとデータが読めない。一方yamlならpyyamlを使うことでdict型を簡単に保存しつつ、テキストエディタからも読めるのでよい。

ハマったこと

dict -> yaml -> dict としたときに、dictの順序がどうなっているか?

pythonは3.7から辞書の順序を保存するようになっているので、当然順序を保存していてほしい……

が、実際は保存しない:

import yaml

din = {"c":3,"b":2, "a":1}

fname = "tmp.yaml"

with open(fname,"w") as f:
    yaml.dump(din,f)
    print(din)
    #  {"c":3,"b":2, "a":1}
    print(yaml.dump(din))
    #  {"a":1,"b":2, "c":3}

with open(fname) as f:
    dout=yaml.safe_load(f)
    print(dout)
    #  {"a":1,"b":2, "c":3}

このようにdumpの段階で順序構造が破壊されてしまう。

解決策

愚直なのは保存時にキーの順序も出力し保存しておく方法。
或いはOrderedDictを使うようにする方法もある。