如何使用 safe_load 使用 PyYAML 反序列化对象?
有这样的片段:
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 表示调用 yaml.load< 并不安全/strong> 从不受信任的来源收到的任何数据;那么,我应该对我的 snippet\class 进行哪些修改才能使用 safe_load 方法?
是否可以?
Having a snippet like this:
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 says that it is not safe to call yaml.load with any data received from an untrusted source; so, what should I modify to my snippet\class to use safe_load method?
Is it possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
还存在另一种方式。来自 PyYaml 文档:
您还必须设置 yaml_tag 属性才能使其正常工作。
YAMLObject 使用一些元类魔法来使对象可加载。请注意,如果这样做,对象将只能由安全加载器加载,而不能使用常规 yaml.load() 加载。
工作示例:
这个的优点是很容易做;缺点是它只能与 safe_load 一起使用,并且会使您的类与序列化相关的属性和元类变得混乱。
Another way exists. From the PyYaml docs:
You also have to set the yaml_tag property to make it work.
YAMLObject does some metaclass magic to make the object loadable. Note that if you do this, the objects will only be loadable by the safe loader, not with regular yaml.load().
Working example:
The advantage of this one is that it's prety easy to do; the disadvantages are that it only works with safe_load and clutters your class with serialization-related attributes and metaclass.
根据定义,safe_load 似乎不允许您反序列化自己的类。如果您希望它安全,我会这样做:
这里的优点是您可以绝对控制您的类的序列化(反)序列化方式。这意味着您不会通过网络获得随机可执行代码并运行它。缺点是您可以绝对控制您的类的序列化(反)序列化方式。这意味着你必须做更多的工作。 ;-)
It appears that safe_load, by definition, does not let you deserialize your own classes. If you want it to be safe, I'd do something like this:
The advantage here is that you have absolute control over how your class is (de)serialized. That means that you won't get random executable code over the network and run it. The disadvantage is that you have absolute control over how your class is (de)serialized. That means you have to do a lot more work. ;-)
如果您有许多标签并且不想为所有标签创建对象,或者如果您不关心返回的实际类型,只关心点访问,则可以使用以下代码捕获所有未定义的标签
:想知道为什么
my_construct_undefined
中间有一个yield
:它允许将对象实例化与其子对象的创建分开。一旦对象存在,就可以引用它(如果它有锚点),并且可以对子对象(或其子对象)进行引用。创建对象的实际机制首先创建它,然后对其执行next(x)
来完成它。If you have many tags and don't want to create objects for all of them, or in case you don't care about the actual type returned, only about dotted access, you catch all undefined tags with the following code:
In case you wonder why the
my_construct_undefined
has ayield
in the middle: that allows for instantiating the object separately from creation of its children. Once the object exist it can be referred to in case it has an anchor and of the children (or their children) a reference. The actual mechanisme to create the object first creates it, then does anext(x)
on it to finalize it.