Perhaps I am doing this the wrong way, but when building REST services in Python 2.7 and trying to be all fancy and object oriented, returning JSON starts to get complicated.
For example, while building a Docker Managment/Statistics tool, I wanted to make sure that the data I retrieve from cAdvisor is nicely handled in classes so that all the data is easy to use and controlled, so I create classes for the cAdvisor data, including container and host machine information.
The "machine" object is inside of the cadvisordata object...
The basic use of these objects is to return as JSON in a rest call, but of course, if I try to just use json.dumps() on the machine.__dict__, i will get an error, since the embedded object will not be parsed as a dict.
Found this very helpful tip on stack exchange....
Which got me thinking, how can I make this something a bit more built-in?
So here was my approach, to include the function as a library function
Then create a method inside of the class in question:
So now I call cadvisorInstance.asdict() instead of cadvisorInstance.__dict__
But this is not very reusable, and doesn't seem very pythonic... I wonder if anyone has done this in a more elegant way? Perhaps creating a base class to inherit from?
For example, while building a Docker Managment/Statistics tool, I wanted to make sure that the data I retrieve from cAdvisor is nicely handled in classes so that all the data is easy to use and controlled, so I create classes for the cAdvisor data, including container and host machine information.
class hostmachine:
def __init__(self,
cpu_frequency=None
,instance_type = None
, memory_capacity= None
, num_cores = None
):
self.cpu_frequency = cpu_frequency
self.instance_type = instance_type
self.memory_capacity = memory_capacity
self.num_cores = num_cores
class cadvisordata:
def __init__(self
, name = None
, interval = None
, dockerid = None
, cpu = None
, network = None
, diskio = None
, machine = None
, machinedata = None
, ts_start = None
, ts_computed = None
, datetime_start = None
, datetime_computed = datetime.now()
, cadvisorpath = None):
"""
:param name: The name of the container
:param interval: the interval that the stats were computed accross
:param dockerid: the internal docker id
:param cpu: cpu stats
:param network: network stats
:param diskio: disk stats
:param machine: host machine info
:param ts_start: the timestamp of the first stats entry
:param ts_computed: the timestamp of the end of the computation
:param datetime_start:
:param datetime_computed:
"""
self.name = name
self.dockerid = dockerid
self.cpu = network
self.network = network
self.diskio = diskio
self.machine = machine
self.ts_start = ts_start
self.ts_computed = ts_computed
self.datetime_start = datetime_start
self.datetime_computed = datetime_computed
self.cadvisorpath = cadvisorpath
self.interval = interval
The "machine" object is inside of the cadvisordata object...
The basic use of these objects is to return as JSON in a rest call, but of course, if I try to just use json.dumps() on the machine.__dict__, i will get an error, since the embedded object will not be parsed as a dict.
So what to do?
Found this very helpful tip on stack exchange....
Which got me thinking, how can I make this something a bit more built-in?
So here was my approach, to include the function as a library function
def todict(obj, classkey=None):
if isinstance(obj, dict):
data = {}
for (k, v) in obj.items():
data[k] = todict(v, classkey)
return data
elif hasattr(obj, "_ast"):
return todict(obj._ast())
elif hasattr(obj, "__iter__"):
return [todict(v, classkey) for v in obj]
elif hasattr(obj, "__dict__"):
data = dict([(key, todict(value, classkey))
for key, value in obj.__dict__.iteritems()
if not callable(value) and not key.startswith('_')])
if classkey is not None and hasattr(obj, "__class__"):
data[classkey] = obj.__class__.__name__
return data
else:
return obj
Then create a method inside of the class in question:
def asdict(self):
"""
Converts the object and all embedded objects to embedded dictionaries
:return: a dictionary of the current object.
:rtype dict
"""
return(todict(self))
So now I call cadvisorInstance.asdict() instead of cadvisorInstance.__dict__
But this is not very reusable, and doesn't seem very pythonic... I wonder if anyone has done this in a more elegant way? Perhaps creating a base class to inherit from?
Comments
Post a Comment