Frage

ein Snippet wie folgt zu haben:

import yaml
class User(object):
    def __init__(self, name, surname):
       self.name= name
       self.surname= surname

user = User('spam', 'eggs')
serialized_user = yaml.dump(user)
#Network
deserialized_user = yaml.load(serialized_user)
print "name: %s, sname: %s" % (deserialized_user.name, deserialized_user.surname)

Yaml docs sagt, dass es nicht sicher ist, zu nennen yaml.load mit beliebigen Daten von einer nicht vertrauenswürdigen Quelle empfangen; so, was soll ich zu meinen Schnipseln \ Klasse Verwendung ändern safe_load Methode?
Ist es möglich?

War es hilfreich?

Lösung

Es scheint, dass safe_load per definitionem nicht lassen Sie Ihre eigenen Klassen deserialisieren. Wenn Sie es sicher sein wollen, ich so etwas tun würde:

import yaml
class User(object):
    def __init__(self, name, surname):
       self.name= name
       self.surname= surname

    def yaml(self):
       return yaml.dump(self.__dict__)

    @staticmethod
    def load(data):
       values = yaml.safe_load(data)
       return User(values["name"], values["surname"])

user = User('spam', 'eggs')
serialized_user = user.yaml()
print "serialized_user:  %s" % serialized_user.strip()

#Network
deserialized_user = User.load(serialized_user)
print "name: %s, sname: %s" % (deserialized_user.name, deserialized_user.surname)

Der Vorteil hierbei ist, dass Sie absolute Kontrolle darüber haben, wie Sie Ihre Klasse (de) serialisiert. Das bedeutet, dass Sie nicht zufällig ausführbaren Code über das Netzwerk erhalten und ausführen. Der Nachteil ist, dass Sie absolute Kontrolle darüber haben, wie Sie Ihre Klasse (de) serialisiert. Das bedeutet Sie haben viel mehr Arbeit zu tun. ; -)

Andere Tipps

Eine andere Möglichkeit besteht. Aus der PyYaml docs:

  

Ein Python-Objekt kann als sicher markiert werden und damit von yaml.safe_load erkannt werden. Um dies zu tun, leiten sie aus yaml.YAMLObject [...] und ausdrücklich seine Klasse Eigenschaft yaml_loader auf yaml.SafeLoader gesetzt.

Sie können auch die yaml_tag Eigenschaft setzen müssen, damit es funktioniert.

YAMLObject hat einige metaclass Magie das Objekt belastbar zu machen. Beachten Sie, dass, wenn Sie dies tun, werden nur die Objekte, die von der sicheren Ladeprogramm, nicht mit regelmäßigen yaml.load ().

belastbar sein

Arbeits Beispiel:

import yaml

class User(yaml.YAMLObject):
    yaml_loader = yaml.SafeLoader
    yaml_tag = u'!User'

    def __init__(self, name, surname):
       self.name= name
       self.surname= surname

user = User('spam', 'eggs')
serialized_user = yaml.dump(user)

#Network

deserialized_user = yaml.safe_load(serialized_user)
print "name: %s, sname: %s" % (deserialized_user.name, deserialized_user.surname)

Der Vorteil dieser ist, dass es die prety einfach zu tun; Die Nachteile sind, dass es nur mit safe_load und clutters Ihre Klasse mit Serialisierung bezogene Attribute und metaclass funktioniert.

Wenn Sie viele Tags haben und nicht wollen, dass Objekte für alle von ihnen erstellen, oder falls Sie kümmern sich nicht um die tatsächliche Typ zurückgegeben, nur etwa gepunkteten Zugang, können Sie alle undefinierten Tags mit dem folgenden Code fangen:

import yaml

class Blob(object):
    def update(self, kw):
        for k in kw:
            setattr(self, k, kw[k])

from yaml.constructor import SafeConstructor

def my_construct_undefined(self, node):
    data = Blob()
    yield data
    value = self.construct_mapping(node)
    data.update(value)

SafeConstructor.add_constructor(None, my_construct_undefined)


class User(object):
    def __init__(self, name, surname):
        self.name= name
        self.surname= surname

user = User('spam', 'eggs')
serialized_user = yaml.dump(user)
#Network
deserialized_user = yaml.safe_load(serialized_user)
print "name: %s, sname: %s" % (deserialized_user.name, deserialized_user.surname)

Falls Sie sich fragen, warum die my_construct_undefined eine yield in der Mitte hat: die von der Erstellung ihrer Kinder zum Instanziieren des Objekts getrennt werden können. Sobald das Objekt existieren kann es bezeichnet werden, falls es einen Anker hat und die Kinder (oder ihre Kinder) Referenz. Die tatsächliche mechanisme das Objekt erstellen zuerst schafft es, tut dann einen next(x) auf, um es fertig zu stellen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top