453 Stimmen

Wie kann ich eine YAML-Datei in eine andere einfügen?

Also habe ich zwei YAML-Dateien, "A" und "B" und ich möchte den Inhalt von A in B einfügen, entweder in die vorhandene Datenstruktur eingeschnitten, wie ein Array, oder als Kind eines Elements, wie der Wert für einen bestimmten Hash-Key.

Ist das überhaupt möglich? Wie? Wenn nicht, gibt es Hinweise auf eine normative Referenz?

2 Stimmen

Ich bin kürzlich auf HiYaPyCo für Python gestoßen, das genau das macht. Sie können verschiedene YAML-Dateien zusammenführen. Es ist ein sehr schönes Python-Modul, das es wert ist, es zu kennen.

0 Stimmen

1voto

jxmallett Punkte 3947

Mit Symfony ermöglicht die Verarbeitung von YAML-Dateien, diese indirekt zu verschachteln. Der Trick besteht darin, die parameters-Option zu nutzen. z.B.:

common.yml

parameters:
    yaml_to_repeat:
        option: "value"
        foo:
            - "bar"
            - "baz"

config.yml

imports:
    - { resource: common.yml }
whatever:
    thing: "%yaml_to_repeat%"
    other_thing: "%yaml_to_repeat%"

Das Ergebnis wird das Gleiche sein wie:

whatever:
    thing:
        option: "value"
        foo:
            - "bar"
            - "baz"
    other_thing:
        option: "value"
        foo:
            - "bar"
            - "baz"

1voto

PaddyM Punkte 11

Ich finde die Lösung, die von @maxy-B verwendet wurde, toll. Allerdings hat es bei mir nicht mit verschachtelten Einschlüssen funktioniert. Wenn zum Beispiel config_1.yaml config_2.yaml einschließt, das config_3.yaml einschließt, gab es ein Problem mit dem Loader. Allerdings, wenn Sie einfach die neue Loader-Klasse bei Laden auf sich selbst verweisen, funktioniert es! Speziell, wenn wir die alte _include-Funktion durch die leicht modifizierte Version ersetzen:

def _include(self, loader, node):                                    
     oldRoot = self.root                                              
     filename = os.path.join(self.root, loader.construct_scalar(node))
     self.root = os.path.dirname(filename)                           
     data = yaml.load(open(filename, 'r'), loader = IncludeLoader)                            
     self.root = oldRoot                                              
     return data

Im Nachhinein stimme ich mit den anderen Kommentaren überein, dass das verschachtelte Laden im Allgemeinen für yaml nicht geeignet ist, da der Eingabestream möglicherweise kein Datei ist, es aber sehr nützlich ist!

0voto

RzR Punkte 2944

Vielleicht könnte dich das inspirieren, versuche dich an den JBB-Konventionen auszurichten:

https://docs.openstack.org/infra/jenkins-job-builder/definition.html#inclusion-tags

- job: name: test-job-include-raw-1 builders: - shell: !include-raw: include-raw001-hello-world.sh

0voto

ram Punkte 113

Als Ergänzung zu @Joshbodes ursprünglicher Antwort oben habe ich den Ausschnitt etwas modifiziert, um UNIX-ähnliche Platzhaltermuster zu unterstützen.

Ich habe es jedoch nicht unter Windows getestet. Ich hatte ein Problem damit, ein Array in einem großen YAML über mehrere Dateien aufzuteilen, um die Wartung zu vereinfachen, und suchte nach einer Lösung, um mehrere Dateien in einem Array des Basis-YAML zu referenzieren. Daher die folgende Lösung. Die Lösung unterstützt keine rekursive Referenz. Sie unterstützt nur Platzhalter in einem angegebenen Verzeichnislevel, die im Basis-YAML referenziert werden.

import yaml
import os
import glob

# Basiskode aus dem folgenden Link übernommen:-
# Verweis: https://stackoverflow.com/a/9577670
class Loader(yaml.SafeLoader):

    def __init__(self, stream):

        self._root = os.path.split(stream.name)[0]

        super(Loader, self).__init__(stream)

    def include(self, node):
        consolidated_result = None
        filename = os.path.join(self._root, self.construct_scalar(node))

        # Der nachstehende Abschnitt wurde für die Unterstützung von UNIX-Platzhaltermustern modifiziert
        filenames = glob.glob(filename)

        # Nur um sicherzustellen, dass die Reihenfolge der berücksichtigten Dateien vorhersehbar ist 
        # und im Fehlerfall leicht zu debuggen ist.
        filenames.sort()
        for file in filenames:
            with open(file, 'r') as f:
                result = yaml.load(f, Loader)

            if isinstance(result, list):
                if not isinstance(consolidated_result, list):
                    consolidated_result = []
                consolidated_result += result
            elif isinstance(result, dict):
                if not isinstance(consolidated_result, dict):
                    consolidated_result = {}
                consolidated_result.update(result)
            else:
                consolidated_result = result

        return consolidated_result

Loader.add_constructor('!include', Loader.include)

Verwendung

a:
  !include a.yaml

b:
  # Alle in der b-Ordner ebene enthaltenen YAMLs werden konsolidiert
  !include b/*.yaml

-8voto

Sankalp Punkte 1930

Möglicherweise wurde es zum Zeitpunkt der Fragestellung nicht unterstützt, aber Sie können eine andere YAML-Datei in eine importieren:

imports: [/Ihr_Standort_zur_YAML-Datei/Util.area.yaml]

Obwohl ich keine Online-Referenz habe, funktioniert das für mich.

5 Stimmen

Dies tut überhaupt nichts. Es erstellt eine Zuordnung mit einer Sequenz, die aus einem einzigen String "/your_location_to_yaml_file/Util.area.yaml" besteht, als Wert für den Schlüssel imports.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X