Domanda

Avere un frammento di simile a questo:

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 dice che non è sicuro di chiamare yaml.load con tutti i dati ricevuti da una fonte non attendibile; così, che cosa devo modificare per il mio frammento di \ classe da utilizzare safe_load metodo?
E 'possibile?

È stato utile?

Soluzione

Sembra che safe_load, per definizione, non lasciate che si deserializzare le proprie classi. Se si vuole che sia al sicuro, mi piacerebbe fare qualcosa di simile:

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)

Il vantaggio è che si ha il controllo assoluto su come la vostra classe è (de) serializzato. Ciò significa che non sarà possibile ottenere il codice eseguibile casuale attraverso la rete ed eseguirlo. Lo svantaggio è che si ha il controllo assoluto su come la vostra classe è (de) serializzato. Ciò significa che si deve fare molto più lavoro. ; -)

Altri suggerimenti

Esiste un altro modo. Dalla documentazione PyYaml:

  

Un oggetto pitone può essere contrassegnato come sicuro e quindi essere riconosciuto da yaml.safe_load. Per fare questo, deriva da yaml.YAMLObject [...] e impostare in modo esplicito la sua yaml_loader proprietà di classe di yaml.SafeLoader.

È inoltre necessario impostare la proprietà yaml_tag per farlo funzionare.

YAMLObject fa qualche magia metaclasse per rendere l'oggetto caricabile. Si noti che se si esegue questa operazione, gli oggetti saranno solo caricabile dal caricatore sicuro, non con yaml.load regolare ().

Esempio di funzionamento:

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)

Il vantaggio di questo è che è prety facile da fare; Gli svantaggi sono che funziona solo con safe_load e ingombra la classe con gli attributi di serializzazione legate all'alimentazione e metaclasse.

Se si dispone di molti tag e non si desidera creare oggetti per tutti loro, o nel caso in cui non si preoccupano per il tipo effettivo restituito, solo circa l'accesso tratteggiata, si cattura tutti i tag non definiti con il seguente codice:

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)

Nel caso in cui chiedersi perché il my_construct_undefined ha un yield in mezzo: che permette di istanziare l'oggetto separatamente dalla creazione dei suoi figli. Una volta che l'oggetto esiste, può essere indicato in caso abbia un ancoraggio e dei bambini (oi loro figli) un riferimento. Il mechanisme reale per creare l'oggetto prima lo crea, poi fa un next(x) su di esso per finalizzarlo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top