PyYAML dump in formato

So che ci sono un paio di domande su questo COSÌ, ma non riuscivo a trovare quello che stavo cercando.

Sto usando pyyaml leggere (.load()) un .yml file, modificare o aggiungere una chiave, e poi scrivere (.dump()) di nuovo. Il problema è che voglio mantenere il file in formato post-dump, ma cambia.

Per esempio, modificare la chiave en.test.index.few dire "Bye" invece di "Hello"

Python:

with open(path, 'r', encoding = "utf-8") as yaml_file:
    self.dict = pyyaml.load(yaml_file)

Poi, dopo la modifica:

with open(path, 'w', encoding = "utf-8") as yaml_file:
    dump = pyyaml.dump(self.dict, default_flow_style = False, allow_unicode = True, encoding = None)
    yaml_file.write( dump )

Yaml:

Prima:

en:
  test:
    new: "Bye"
    index:
      few: "Hello"
  anothertest: "Something"

Dopo:

en:
  anothertest: Something
  test:
    index:
      few: Hello
    new: Bye

C’è un modo per mantenere lo stesso formato?, per esempio il qoutes e l’ordine. Sto usando lo strumento sbagliato per questo?

Che ne so magari il file originale non è del tutto corretto, ma non ho alcun controllo su di esso (è un Ruby on Rails file i18n).

Vi ringrazio molto.

  • yaml.dump ha un default_style argomento. Utilizzando default_style='"' mancherà di tenere i vostri valori di stringa tra doppi apici, ma le chiavi e qualsiasi altri tipi di valore anche essere racchiuso tra doppi apici.
  • Grazie!, Terrò a mente, sarebbe stato davvero utile se non fosse per i tasti 🙁
  • Probabilmente hanno un tempo difficile ordinare le chiavi, troppo. yaml.load ti dà un dict; i tasti sono non ordinato. yaml.dump probabilmente uscite in qualunque ordine di iterazione va.
  • Il nuovo file rappresenta esattamente le stesse informazioni (in YAML) come file di origine; non c’è motivo di mantenere lo stesso formato.
  • questo è vero, ma ho voluto mantenere il formato perché è utile, dato il contesto sublime pacchetto che ho creato github.com/NicoSantangelo/sublime-text-i18n-rails



3 Replies
  1. 74

    Utilizzare ruamel.yaml invece.

    Biblioteca Lotta! Un Racconto di Due Librerie

    PyYAML è effettivamente morto ed è stato per diversi anni. A peggiorare le cose, il progetto ufficiale casa http://pyyaml.org sembra essere stato tolto di recente. Questo sito ha ospitato la PyYAML issue tracker, documentazione, e download. Come di questa scrittura, tutti se ne sono andati. Questo è a dir poco disastrose. Benvenuti a solo un altro giorno in open-source.

    ruamel.yaml è attivamente mantenuto. A differenza di PyYAML, ruamel.yaml supporta:

    • YAML <= 1.2. PyYAML supporta solo YAML <= 1.1. Questo è di vitale importanza, come YAML 1.2 intenzionalmente pause compatibilità con YAML 1.1 in alcuni casi limite. Questo sarà solitamente una brutta cosa. In questo caso, questo rende YAML 1.2 una rigorosa superset di JSON. Dal YAML 1.1 è non un rigoroso superset di JSON, questa è una buona cosa.
    • Di andata e ritorno di conservazione. Quando si chiama yaml.dump() per scaricare un dizionario caricato da una precedente chiamata a yaml.load():
      • PyYAML ingenuamente ignora tutti gli input di formattazione – compresi i commenti, ordinazione, citando, e gli spazi vuoti. Scartato piace molto il digitale rifiuti nel più vicino secchio bit.
      • ruamel.yaml abilmente rispetta tutti ingresso di formattazione. Tutto. Tutta la stilistica enchilada. L’intero letterario shebang. Tutti.

    Libreria Migrazione: Il Sentiero del Codice di Lacrime

    Dal ruamel.yaml è un PyYAML forcella e, quindi, conforme al PyYAML API, il passaggio da PyYAML per ruamel.yaml in applicazioni esistenti in genere è così semplice come la sostituzione di tutte le istanze di questo:

    # This imports PyYAML. Stop doing this.
    import yaml

    …con questo:

    # This imports "ruamel.yaml". Always do this.
    from ruamel import yaml

    Che è.

    Altre modifiche dovrebbero essere necessari. Il yaml.load() e yaml.dump() funzioni deve continuare a comportarsi come previsto – con i benefici aggiunti di sostenere YAML 1.2 e la ricezione correzioni di bug.

    Di andata e ritorno di Conservazione e che Cosa Può Fare per Voi

    Per la compatibilità con PyYaml, il yaml.load() e yaml.dump() funzioni non eseguire andata e ritorno di conservazione per impostazione predefinita. Per fare ciò, passare in modo esplicito:

    • Opzionale Loader=ruamel.yaml.RoundTripLoader parola chiave parametro yaml.load().
    • Opzionale Dumper=ruamel.yaml.RoundTripDumper parola chiave parametro yaml.dump().

    Un esempio gentilmente “preso in prestito” da ruamel.yaml documentazione:

    import ruamel.yaml
    
    inp = """\
    # example
    name:
      # Yet another Great Duke of Hell. He's not so bad, really.
      family: TheMighty
      given: Ashtaroth
    """
    
    code = ruamel.yaml.load(inp, Loader=ruamel.yaml.RoundTripLoader)
    code['name']['given'] = 'Astarte'  # Oh no you didn't.
    
    print(ruamel.yaml.dump(code, Dumper=ruamel.yaml.RoundTripDumper), end='')

    È fatto. Commenti, ordinazione, citando, e che spazi ora essere conservato intatto.

    tl;dr

    Utilizzare sempre ruamel.yaml. Non utilizzare mai PyYAML. ruamel.yaml vita. PyYAML è un fetido cadavere in decomposizione in mouldering ossario terra di PyPi.

    Viva ruamel.yaml.

    • Devo dire che questa è una bella risposta. Attualmente sto sviluppando non è il progetto che ha usato PyYAML ma io sicuramente dare ruamel.yaml una prova, quando ho un po ‘ di tempo e di accettare la risposta, se funziona. Grazie!
    • In effetti non mantenere tutta la formattazione. Per esempio, cita non vengono conservati.
    • Se ruamel.yaml non andata e ritorno preservare qualsiasi formattazione (tra cui, ma non limitato a citare stile), che è un bug. Considerare l’invio di un problema al ruamel.yaml‘s problemi. le principali manutentore di ruamel.yaml è molto ricettivo e accogliente, per fortuna. Evviva!
    • A partire ruamel.yaml 0.11.12 è possibile specificare preserve_quotes=True durante il caricamento, avvolgere le corde caricato con le informazioni necessarie per il dumping. Vedi anche questa risposta
    • Sarà in qualche modo preservare le righe vuote tra i dati?
    • Si, funziona. Le righe vuote sono considerate commenti senza # e sono conservati. Ma nel caso in cui sarete inserimento di nuovi valori, attenzione che i commenti/le righe vuote sono attualmente collegati alla mappatura tasti/elementi di sequenza prima il commento (ossia commento raduno è avido), anche se visivamente potrebbe essere “vicino” alla seguente chiave/elemento
    • Che bello sentire. Ho un sacco di problemi e cercherò di farli crescere in Bitbucket. Il progetto è fantastico, è quasi incredibile che nessuno ci ha pensato prima!
    • È questo il commento è ancora aggiornato con l’attuale stato di PyYAML?
    • PyYAML è il nuovo maintainer ora, e aveva un v4.1 per il rilascio di recente. La risposta è obsoleta e sciocco di contenuti come “PyYAML è un fetido cadavere in decomposizione..”, probabilmente, dovrebbe essere modificato.
    • aaaand PyYAML sviluppo macinato si fermano di nuovo, senza cambiamenti significativi da più di 5 mesi. La release 4.1 di si è rotto varie progetti, e ci sono attualmente seduto su 4.2b4, che è piuttosto imbarazzante. C’è poca speranza che mai viene un corretto rilascio e un sacco di rammarico per non aver scelto ruamel, in primo luogo.
    • 3.x a 4.x è un numero di versione principale bump, così indietro incompat modifiche dovrebbe essere previsto. Non sto negando PyYAML maintainership ha problemi e la politica, ma il linguaggio usato in questa risposta è un po ‘ eccessivo. Si legge come un annuncio per ruamel.yaml o di propaganda.
    • Ancora morti. Mai fidarsi di una release, solo un modello di release. Long live ruamel.yaml
    • Ho paura che il “nuovo” PyYAML è molto carente dal punto di vista della fruibilità, in Python ambiente. Alcuni “manutentori” sono armeggiare intorno, mentre sono certamente “imparare Python”. E combattono ferocemente contro ovvie richieste simili a preservare dizionario ordine come Python fa. È un peccato per un tale progetto.
    • mentre ruamel funziona meglio, anche difettoso. Lo stato di yaml caricamento + dumping in python è, purtroppo, molto male.
    • ruamel.yaml è significantlly più lento di pyyaml. Qualcosa da tenere a mente
    • Questa risposta dovrebbe essere corretto. Si inizia subito con false dichiarazioni. Forse si è vero, al momento è stato scritto, ma non è più il caso. PyYaml non è morto, e il sito web è attivo. Al momento di scrivere questo commento, PyYaml sembra ancora vivo e vegeto. Guarda le ultime uscite: – 2019-07-30: PyYAML 5.1.2 viene rilasciato. – 2018-06-06: PyYAML 5.1.1 viene rilasciato. – 2019-03-13: LibYAML 0.2.2 e PyYAML 5.1 vengono rilasciati. – 2018-07-05: PyYAML 3.13 viene rilasciato. – 2018-06-24: LibYAML 0.2.1 viene rilasciato. Questa risposta è fuorviante.

  2. 2

    Primo

    Per rappresentare dizionario di dati è utilizzato il seguente codice:

    mapping = list(mapping.items())
        try:
            mapping = sorted(mapping)
        except TypeError:
            pass

    È il motivo per cui l’ordinamento è cambiato

    Secondo

    Informazioni su come scalare tipo è stato presentato (con virgolette doppie o non) viene persa durante la lettura (questo è il principale approccio di biblioteca)

    Riepilogo

    È possibile creare la propria classe, basata su un “Dumper”, e al metodo di overload ‘represent_mapping’ per modificare i comportamenti come il dizionario verrà presentato

    Per il salvataggio di informazioni circa il doppio preventivi per scalare è inoltre necessario creare una classe personalizzata, basata su un “Loader”, ma ho paura che interesserà e altre classi e si fa difficile

    • Farò una prova!
  3. 1

    Nel mio caso, voglio " se il valore contiene un { o un }, altrimenti niente. Per esempio:

     en:
       key1: value is 1
       key2: 'value is {1}'

    Di eseguire, copiare funzione represent_str() da file representer.py nel modulo PyYaml e usare un altro stile se la stringa contiene { o un }:

    def represent_str(self, data):
        tag = None
        style = None
        # Add these two lines:
        if '{' in data or '}' in data:
            style = '"'
        try:
            data = unicode(data, 'ascii')
            tag = u'tag:yaml.org,2002:str'
        except UnicodeDecodeError:
            try:
                data = unicode(data, 'utf-8')
                tag = u'tag:yaml.org,2002:str'
            except UnicodeDecodeError:
                data = data.encode('base64')
                tag = u'tag:yaml.org,2002:binary'
                style = '|'
        return self.represent_scalar(tag, data, style=style)

    Di usarlo nel tuo codice:

    import yaml
    
    def represent_str(self, data):
      ...
    
    yaml.add_representer(str, represent_str)

    In questo caso, non diffences tra chiavi e valori, e questo è abbastanza per me. Se volete un stile diverso per le chiavi e valori, eseguire la stessa cosa con la funzione represent_mapping

Lascia un commento