Pregunta

Tener un fragmento de esta manera:

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 que no es seguro llamar a yaml.load con cualquier dato recibido de una fuente no confiable; así, ¿cuál debería modificar a mi fragmento \ clase que se utiliza safe_load método?
¿Es posible?

¿Fue útil?

Solución

Parece que safe_load, por definición, no deje que deserializar sus propias clases. Si usted quiere que sea seguro, me gustaría hacer algo como esto:

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)

La ventaja aquí es que usted tiene el control absoluto sobre la forma en que su clase es (de) serializado. Eso significa que usted no conseguirá código ejecutable al azar través de la red y ejecutarlo. La desventaja es que usted tiene el control absoluto sobre la forma en que su clase es (de) serializado. Eso significa que tiene que hacer mucho más trabajo. ; -)

Otros consejos

Existe otra manera. A partir de los documentos PyYAML:

  

Un objeto pitón puede ser marcados como seguros y por lo tanto ser reconocido por yaml.safe_load. Para ello, derivarla de yaml.YAMLObject [...] y establecer explícitamente su yaml_loader propiedad de clase a yaml.SafeLoader.

También tiene que establecer la propiedad yaml_tag para hacer que funcione.

YAMLObject hace un poco de magia para hacer que la metaclase cargable objeto. Tenga en cuenta que si lo hace, los objetos serán sólo se puede cargar por el cargador seguro, no con yaml.load regular ().

Ejemplo de trabajo:

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)

La ventaja de éste es que es fácil de hacer prety; las desventajas son que sólo funciona con safe_load y estorba su clase con atributos y metaclase relacionados serialización.

Si usted tiene muchas etiquetas y no desea crear objetos para todos ellos, o en caso de que no se preocupan por el tipo real regresó, sólo el acceso de puntos, que captura todas las etiquetas definidas por el código siguiente:

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)

En caso de que preguntarse por qué el my_construct_undefined tiene una yield en el medio: que permite crear instancias de objeto separado de la creación de sus hijos. Una vez que el objeto existe puede ser mencionado en el caso de que tenga un ancla y de los niños (o sus hijos) una referencia. El mechanisme real para crear el objeto crea en primer lugar, y luego hace un next(x) en él para finalizarlo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top