有一个片段是这样的:

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文档说,这是不是安全地调用 yaml.load 使用来自非置信源接收的任何数据;所以,我应该怎么修改我的片段\类使用 safe_load 方式?点击 这可能吗?

有帮助吗?

解决方案

看起来safe_load,顾名思义,不会让你反序列化自己的类。如果你希望它是安全的,我会做这样的事情:

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)

这里的好处是,你有过连载类是如何绝对控制的(de)。这意味着你不会在网络上看到一些随机的可执行代码并运行它。缺点是,你必须在序列化类是如何绝对控制的(de)。这意味着你必须做很多工作。 ; - )

其他提示

另一种方式中存在。从PyYaml文档:

  

一个蟒对象可以被标记为安全的,因此通过yaml.safe_load识别。要做到这一点,从yaml.YAMLObject [...]得到它,并明确设置它的类属性yaml_loader到yaml.SafeLoader。

您还必须设置yaml_tag属性,使其工作。

YAMLObject做一些元类魔法使该对象可加载。请注意,如果你这样做,对象将只加载在安全装载,不与普通yaml.load()。

工作示例:

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)

这一项的优点是,它的prety容易做到;缺点是,它只能与safe_load和杂波类系列化相关的属性和元类的作品。

如果您有多个标签,不希望为所有这些创建对象,或者如果你不关心的实际类型返回,大约只有点访问,你赶上用下面的代码的所有未定义的标签:

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)

如果你想知道为什么my_construct_undefined在中间的yield:允许从创立了孩子的独立实例化对象。一旦对象存在,可以被称为在情况下,它具有锚定和孩子(或他们的孩子)的引用的。实际mechanisme先创建对象创建它,然后做在其上的next(x)定稿。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top