I need to convert string object location to an object. My code is:
class Dog:
def __init__(self,name):
self.name= name
def bark(self):
print('BAR')
b=''
a=Dog('Test')
print(a)
with open('Dog.txt','w') as file:
file.write(str(a))
with open('Dog.txt','r') as file:
b=file.read()
b=repr(b)
print(b)
b.bark()
I saved the object a
in a Dog.txt
file <__main__.Dog object at 0x0000024E1C7AFE80>
and now i want to take that string and convert it to an object so I can use the bark
method with it.
How can I do this
you can use PyYAML:
pip install PYyaml
and dump and load data from yaml files:
In [1]: class Dog:
...: def __init__(self,name):
...: self.name= name
...:
...: def bark(self):
...: print('BAR')
...:
...: b=''
...:
...: a=Dog('Test')
...: print(a)
...:
...:
<__main__.Dog object at 0x7fb082811390>
now dump you object to the yaml
:
In [2]: import yaml
In [3]: with open('data.yml', 'w') as outfile:
...: yaml.dump(a, outfile, default_flow_style=False)
inside the data.yml
you will see:
!!python/object:__main__.Dog
name: Test
and now load:
In [6]: with open('data.yml', 'r') as loadfile:
...: data = yaml.load_all(loadfile)
...: b = next(data)
...:
In [7]: b
Out[7]: <__main__.Dog at 0x7fb07bfd5f28>
In [8]: b.bark()
BAR
You cannot recover an object from its string representation. You should instead serialize the object before dumping it to the file. You can use pickle
for this
>>> a
<__main__.Dog object at 0x7f6d4ee8fb38>
>>>
>>> pickle.dump(a, open('Dog.txt', 'wb'))
>>> b = pickle.load(open('Dog.txt', 'rb'))
>>> b
<__main__.Dog object at 0x7f6d4ee8fac8>
>>> b.bark()
BAR
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
)