Sie erhalten null
weil dump()
die Representer()
verwendet, die SafeRepresenter()
Unterklassen und None
darzustellen, wird das folgende Verfahren genannt:
def represent_none(self, data):
return self.represent_scalar(u'tag:yaml.org,2002:null',
u'null')
Als String null
hartcodiert ist, gibt es keine Möglichkeit, dump()
das zu ändern.
Der richtige Weg, dies in PyYAML zu lösen, ist Ihre eigene Dumper
Unterklasse, die die Emitter
, Serializer
und Resolver
von dem Standard Dumper
dass dump()
Anwendungen hat zu machen, aber mit Unterklasse von Representer
, der darstellt, None
so, wie Sie es wollen:
import sys
import yaml
from yaml.representer import Representer
from yaml.dumper import Dumper
from yaml.emitter import Emitter
from yaml.serializer import Serializer
from yaml.resolver import Resolver
yaml_str = """\
attrs:
first:
second: value2
"""
class MyRepresenter(Representer):
def represent_none(self, data):
return self.represent_scalar(u'tag:yaml.org,2002:null',
u'')
class MyDumper(Emitter, Serializer, MyRepresenter, Resolver):
def __init__(self, stream,
default_style=None, default_flow_style=None,
canonical=None, indent=None, width=None,
allow_unicode=None, line_break=None,
encoding=None, explicit_start=None, explicit_end=None,
version=None, tags=None):
Emitter.__init__(self, stream, canonical=canonical,
indent=indent, width=width,
allow_unicode=allow_unicode, line_break=line_break)
Serializer.__init__(self, encoding=encoding,
explicit_start=explicit_start, explicit_end=explicit_end,
version=version, tags=tags)
MyRepresenter.__init__(self, default_style=default_style,
default_flow_style=default_flow_style)
Resolver.__init__(self)
MyRepresenter.add_representer(type(None),
MyRepresenter.represent_none)
data = yaml.load(yaml_str)
yaml.dump(data, stream=sys.stdout, Dumper=MyDumper, default_flow_style=False)
gibt Ihnen:
attrs:
first:
second: value2
Wenn das klingt wie eine Menge Overhead nur um null
loszuwerden, ist es. Es gibt einige Verknüpfungen, die Sie verwenden können, und Sie können sogar versuchen, die alternative Funktion auf die vorhandene Representer
zu übertragen, aber da die tatsächliche Funktion in einer Nachschlagetabelle referenziert wird (add_representer
), müssen Sie mindestens diese Referenz auch behandeln.
Die weitaus einfache Lösung ist PyYAML mit ruamel.yaml
ersetzen und seine round_trip Funktionalität nutzen (Disclaimer: Ich bin der Autor dieses Pakets):
import ruamel.yaml
yaml_str = """\
# trying to round-trip preserve empty scalar
attrs:
first:
second: value2
"""
data = ruamel.yaml.round_trip_load(yaml_str)
assert ruamel.yaml.round_trip_dump(data) == yaml_str
abgesehen von None
als leeren Skalar emittiert, es auch Konserven Reihenfolge in Mapping-Keys, Kommentaren und Tag-Namen, von denen keiner PyYAML tut. ruamel.yaml
folgt ebenfalls der Spezifikation YAML 1.2 (ab 2009), wobei PyYAML das ältere YAML 1.1 verwendet.
Das ruamel.yaml
Paket kann mit pip
von PyPI oder mit modernen Debian-basierten Distributionen, auch mit apt-get python-ruamel.yaml
Gibt es einen bestimmten Grund, dass Sie null (None) Leerzeilen in Dumped Yaml benötigen? – Alik
Wir erstellen ein Datenerfassungssystem für nicht-technische Benutzer und möchten, dass die Schnittstelle sehr einfach ist. Wir entschieden uns für Leerzeichen anstelle von Null für die Eingabe, und es wäre großartig, wenn die Ausgabe die Eingabe so viel wie möglich replizieren würde. – delgadom