久久国产乱子伦精品免费M,亚洲一区二区三区91,欧美国产在线视频,国产精品视频久久

很實用的 PyYAML 使用技巧

YAML 是一個被廣泛使用的數據序列化和配置語言,作為一個開發者,總是不免和它打交道。但處理 YAML 文檔,尤其是使用 PyYAML 的過程總是非常痛苦。

這篇文章分享我在 Python 下使用 PyYAML 的技巧和代碼片段,并介紹幾個相關的庫。

注意:本文中的代碼僅保證在 Python 3 下正常工作

總是使用?safe_load/safe_dump

PyYAML 的?load?函數可以構造任意 Python 對象(Pickle 協議),這意味著一次?load?可能導致任意 Python 函數被執行。

為了確保應用程序的安全性,盡量在任何情況下使用?yaml.safe_load?和?yaml.safe_dump

保留字段順序

Python 3.7+ 中,dict?keys 具備保留插入順序的特性,所以通過?yaml.safe_load?得到的?dict,其 keys 順序會與原始文件保持一致。

>>>?import?yaml
>>>?text?=?"""---
...?c:?1
...?b:?1
...?d:?1
...?a:?1
...?"""
>>>?d?=?yaml.safe_load(text)
>>>?d
{'c':?1,?'b':?1,?'d':?1,?'a':?1}
>>>?list(d)
['c',?'b',?'d',?'a']

當把?dict?導出為 YAML 字符串時,為?yaml.safe_dump?傳遞?sort_keys=False?來保留 keys 的順序。

>>>?print(yaml.safe_dump(d))
a:?1
b:?1
c:?1
d:?1
>>>?d['e']?=?1
>>>?print(yaml.safe_dump(d,?sort_keys=False))
c:?1
b:?1
d:?1
a:?1
e:?1

如果 Python 版本較低,或者你想確保代碼能在更廣泛的環境下工作,你可以使用?oyaml?庫來代替 PyYAML 的?yaml?包。

>>>?import?oyaml?as?yaml
>>>?d?=?yaml.safe_load(text)
>>>?d
OrderedDict([('c',?1),?('b',?1),?('d',?1),?('a',?1)])
>>>?d['e']?=?1
>>>?print(yaml.safe_dump(d,?sort_keys=False))
c:?1
b:?1
d:?1
a:?1
e:?1

優化列表項的縮進

默認情況下,PyYAML 輸出的列表縮進與其父元素一致。

>>>?d?=?{'a':?[1,?2,?3]}
>>>?print(yaml.safe_dump(d))
a:
-?1
-?2
-?3

這并不是很好的格式,根據 Ansible 和 HomeAssistant 等 YAML 書寫規范,列表項應該縮進 2 空格。

這種格式也會對導致列表項不會被如 VSCode 等編輯器識別,進而無法使用編輯器的折疊功能。

要解決這個問題,使用如下代碼片段,在代碼中定義?IndentDumper?class:

class?IndentDumper(yaml.Dumper):
????def?increase_indent(self,?flow=False,?indentless=False):
????????return?super(IndentDumper,?self).increase_indent(flow,?False)

然后將它傳遞給?yaml.dump?的?Dumper?關鍵字參數。

>>>?print(yaml.dump(d,?Dumper=IndentDumper))
a:
??-?1
??-?2
??-?3

注意,yaml.safe_dump?由于有自己的 Dumper class,傳遞此參數會造成沖突。

輸出可讀的 UTF-8 字符

默認情況下,PyYAML 假設你希望輸出的結果里只有 ASCII 字符。

>>>?d?=?{'a':?'你好'}
>>>?print(yaml.safe_dump(d))
a:?"\u4F60\u597D"

這會讓輸出結果非常難以閱讀。

在 UTF-8 足夠普及的今天,直接輸出 UTF-8 字符是非常安全的。因此我們可以將?allow_unicode=True?傳入?yaml.safe_dump?使 PyYAML 將 Unicode 轉換成 UTF-8 字符串。

>>>?print(yaml.safe_dump(d,?allow_unicode=True))
a:?你好

一些 YAML 相關的庫

oyaml

Link:?https://github.com/wimglenn/oyaml

正如上文中提到的,oyaml 是?yaml?包的替換品,使?dict?keys 的順序在 dump/load 的時候得以保留。

oyaml 是一個單文件庫,只有 53 行代碼,因此使用起來非常靈活,你可以直接把它的代碼復制到自己的項目中,然后根據自己的需求進行修改。

strictyaml

Link:?https://github.com/crdoconnor/strictyaml

有的人說 YAML 過于復雜和靈活,不是一個好的配置語言。但我認為這不是 YAML 的問題,而是使用方式的問題。如果我們限制程序只使用 YAML 的部分功能,YAML 其實可以變得像它設計的那般好用。

這就是 StrictYAML 的設計意圖,它是一個類型安全的 YAML 解析器,實現了 YAML 規范說明中的一個子集?。

如果你對 YAML 的輸入輸出有較強的安全考慮,建議使用 StrictYAML 代替 PyYAML。

順帶一提的是,StrictYAML 的文檔站有很多關于設計細節和配置語言思考的文章,非常值得一看。

ruamel.yaml

Link:?https://yaml.readthedocs.io/en/latest/overview.html

ruamel.yaml 是 PyYAML 的一個分叉,于 2009 年發布并持續維護至今。

ruamel.yaml 的文檔里詳細說明了它和 PyYAML 的差異。總體來說,ruamel.yaml 專注在 YAML 1.2 上,對一些語法進行了優化。

ruamel.yaml 最令我感興趣的特性是輸入輸出的 “round-trip”,可以最大程度地保留輸入源的原始格式。官方文檔中的定義是這樣的:

A round-trip is a YAML load-modify-save sequence and ruamel.yaml tries to preserve, among others:

  • comments
  • block style and key ordering are kept, so you can diff the round-tripped source
  • flow style sequences ( ‘a: b, c, d’) (based on request and test by Anthony Sottile)
  • anchor names that are hand-crafted (i.e. not of the formidNNN)
  • merges?in dictionaries are preserved

如果你有盡可能保留原始格式的需求,建議使用 ruamel.yaml 代替 PyYAML。

在使用中我注意到 ruamel.yaml 的 safe load 方法 (YAML(typ='safe').load) 與 PyYAML 有些不同,它無法解析 flow style 的集合定義 (如?a: {"foo": "bar"}),這點沒有在文檔中提及,使用時須多加注意。

總結

YAML 有它好的地方和壞的地方。它易于閱讀,初期的學習曲線非常平緩。但 YAML 的規范說明非常復雜,不僅造成了使用中的混亂,也使不同語言的實現在很多細微的地方難以保持一致。

盡管有這些小毛病,YAML 仍然是我心中最好的配置語言。希望這篇文章所介紹的技巧能夠幫助你避免問題,獲得更好的開發和使用體驗。

鏈接:https://reorx.com/blog/python-yaml-tips-zh/

(版權歸原作者所有,侵刪)

相關新聞

歷經多年發展,已成為國內好評如潮的Linux云計算運維、SRE、Devops、網絡安全、云原生、Go、Python開發專業人才培訓機構!

    1. 主站蜘蛛池模板: 柘城县| 南通市| 禹城市| 浦江县| 那曲县| 亳州市| 和田县| 杭锦旗| 东方市| 赤水市| 囊谦县| 金阳县| 龙门县| 彰武县| 永川市| 饶平县| 安国市| 郎溪县| 林芝县| 藁城市| 新疆| 民丰县| 新乡市| 积石山| 通州市| 德安县| 镇平县| 东源县| 中山市| 婺源县| 宜阳县| 武乡县| 长宁县| 建平县| 清涧县| 清水河县| 茌平县| 从化市| 廉江市| 武陟县| 泸溪县|