Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursively dump an object

Tags:

python

I am not sure if there is a standard way of doing this. I have implemented the following function to dump all contents of an object. It must recursively dump sub-objects, so I am checking for InstanceType, but it does not work:

import types

def dump_obj(obj, level=0):
    for a in dir(obj):
        try:
            if type(obj.__dict__[a]) == types.InstanceType:
                dump_obj(obj.__dict__[a], level + 2)
            else:
                try:
                    print " " * level + "%s -> %s" % (a, obj.__dict__[a])
                except:
                    pass
        except:
            pass

How can I verify if an element is itself an object?

What I actually want is the following. Given:

class B:
  def __init__(self):
    self.txt = 'bye'

class A:
  def __init__(self):
    self.txt = 'hello'
    self.b = B()

a = A()

dump_obj(a)

I want the following output:

txt -> hello
  txt -> bye
like image 886
blueFast Avatar asked May 03 '13 08:05

blueFast


2 Answers

This will recursively dump any object and all sub-objects. The other answers worked for simple examples, but for complex objects, they were missing some data.

import jsonpickle # pip install jsonpickle
import json

serialized = jsonpickle.encode(obj)
print(json.dumps(json.loads(serialized), indent=2))

EDIT: If you use YAML format, it will be even closer to your example.

import yaml # pip install pyyaml
print(yaml.dump(yaml.load(serialized), indent=2))
like image 51
wisbucky Avatar answered Oct 20 '22 03:10

wisbucky


It is always better to use isinstance(x, y) instead of type(x) == y.

Since everything is an object in Python, it doesn't make sense to do isinstance(attr, object), because (I guess) it always returns true.

Your best bet is to "blacklist" certain types. For example, you check if it's other than int, float, str, unicode, list, dict, set, ... you go deeper, otherwise you just print it.

For example:

def dump(obj, level=0):
   for a in dir(obj):
      val = getattr(obj, a)
      if isinstance(val, (int, float, str, unicode, list, dict, set)):
           print level*' ', val
      else:
           dump(val, level=level+1)

UPDATE: isinstance takes into account inheritance, so if you try to see if an object is an instance of a parent class, it will return True while it may not when using type.

Since in this case you'll be testing against primitive types, it may not make any difference in this case, but in general isinstance is preferable.

See this example:

>>> class A(object): pass
... 
>>> class B(A): pass
... 
>>> a, b = A(), B()
>>> type(a)
<class '__main__.A'>
>>> type(a) == A
True
>>> type(b)
<class '__main__.B'>
>>> type(b) == B
True
>>> type(b) == A
False
>>> 

You can check out the docs

like image 43
jadkik94 Avatar answered Oct 20 '22 03:10

jadkik94