<===
2026-02-16 11:36:29
Проверяем синтаксис YAML своими руками на Python
При работе с Prometheus и другими системами конфигурации на YAML удобно иметь быстрый CLI‑инструмент, который просто отвечает: “конфиг валиден / конфиг битый”. В этой мини‑статье сделаем две реализации на Python:
Вариант 1 — дополнительный линт отступов и табов.
Вариант 2 — проверка через парсер PyYAML.
########## test yml самодостаточный ###########################
#!/usr/bin/env python3
import argparse
import sys
from pathlib import Path
import yaml # pip install pyyaml [web:21][web:24]
def check_yaml(path: Path) -> bool:
try:
with path.open("r", encoding="utf-8") as f:
yaml.safe_load(f)
print(f"[OK] {path}")
return True
except yaml.YAMLError as e:
print(f"[ERROR] {path}")
print(e)
return False
except OSError as e:
print(f"[ERROR] {path}: {e}")
return False
def iter_paths(targets, recursive: bool):
for t in targets:
p = Path(t)
if p.is_dir():
if recursive:
for f in p.rglob("*.yml"):
yield f
for f in p.rglob("*.yaml"):
yield f
else:
for f in p.glob("*.yml"):
yield f
for f in p.glob("*.yaml"):
yield f
else:
yield p
def main(argv=None) -> int:
parser = argparse.ArgumentParser(
prog="pyyamllint",
description="Simple YAML syntax checker based on PyYAML.",
) # [web:42][web:49]
parser.add_argument(
"paths",
nargs="+",
help="Files or directories to check (YAML files).",
)
parser.add_argument(
"-r",
"--recursive",
action="store_true",
help="Recurse into directories.",
)
args = parser.parse_args(argv)
ok = True
for path in iter_paths(args.paths, args.recursive):
if not check_yaml(path):
ok = False
return 0 if ok else 1
if __name__ == "__main__":
raise SystemExit(main())
########## test yml ###########################
#!/usr/bin/env python3
import sys
import yaml
def check_yaml(path: str) -> int:
try:
with open(path, "r", encoding="utf-8") as f:
yaml.safe_load(f) # пробуем распарсить [web:21][web:24]
print(f"[OK] {path}")
return 0
except yaml.YAMLError as e:
print(f"[ERROR] {path}")
# PyYAML обычно даёт строку/колонку
print(e)
return 1
if __name__ == "__main__":
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} file1.yml [file2.yml ...]")
sys.exit(1)
rc = 0
for p in sys.argv[1:]:
rc |= check_yaml(p)
sys.exit(rc)
######## example #################
---
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets:
- "localhost:9090"
alerting:
alertmanagers:
- static_configs:
- targets:
- "alertmanager:9093"
...
Back to list