Both Bear Brown and Sunitha fail to mention that the loading they propose to do
can be unsafe. For PyYAML this is clearly indicated at the start of the
tutorial:
Warning: It is not safe to call yaml.load with any data received
from an untrusted source! yaml.load is as powerful as pickle.load
and so may call any Python function
Pickle has a similar warning:
Warning The pickle module is not secure against erroneous or
maliciously constructed data. Never unpickle data received from an
untrusted or unauthenticated source
At least using YAML, it is not necessary to run any risks now or in the future.
First do:
pip install ruamel.yaml
Then:
from ruamel.yaml import YAML
class Dog:
# yaml_tag = u'!Doggie'
def __init__(self, name):
self.name = name
def bark(self):
print('BARK')
b = ''
a = Dog('Test')
yaml = YAML(typ='safe')
yaml.register_class(Dog)
with open('Dog.yaml','w') as ofp:
yaml.dump(a, ofp)
with open('Dog.yaml') as ifp:
b = yaml.load(ifp)
print(b.name, b)
b.bark()
print('==========')
with open('Dog.yaml') as ifp:
print(ifp.read(), end='')
which gives:
Test <__main__.Dog object at 0x7f88a5479320>
BARK
==========
!Dog {name: Test}
Notes:
- The "official" FAQ on yaml.org asks to use
.yaml as the file
extension for files containing YAML.
- You can uncomment the "
yaml_tag =" line, to use a different tag in YAML document
than the default (i.e. your class name)
- Not only is this safe, it also doesn't have
__main__ in the YAML file, which is
essential if you ever decide to move the class definition to a different file.
- Although not as fast as using pickle, the above is much (~10x) faster than the solution
Bear Brown proposes. That might be relevant if you have 101 Dalmatians
to dump and load.
- It is not noticeable in your example data, but the above loads/dumps YAML according to the
YAML 1.2 specification (published 2009) and also supports the long outdated YAML 1.1 specification. PyYAML has never been updated and still only supports YAML 1.1.
(Disclaimer: I am the author of ruamel.yaml)