49
votes

Is there a Python module that can be used in the same way as Perl's Data::Dumper module?

Edit: Sorry, I should have been clearer. I was mainly after a module for inspecting data rather than persisting.

BTW Thanks for the answers. This is one awesome site!

11

11 Answers

34
votes

Data::Dumper has two main uses: data persistence and debugging/inspecting objects. As far as I know, there isn't anything that's going to work exactly the same as Data::Dumper.

I use pickle for data persistence.

I use pprint to visually inspect my objects / debug.

9
votes

I think the closest you will find is the pprint module.

>>> l = [1, 2, 3, 4]
>>> l.append(l)
>>> d = {1: l, 2: 'this is a string'}
>>> print d
{1: [1, 2, 3, 4, [...]], 2: 'this is a string'}

>>> pprint.pprint(d)
{1: [1, 2, 3, 4, <Recursion on list with id=47898714920216>],
 2: 'this is a string'}
6
votes

Possibly a couple of alternatives: pickle, marshal, shelve.

4
votes

I too have been using Data::Dumper for quite some time and have gotten used to its way of displaying nicely formatted complex data structures. pprint as mentioned above does a pretty decent job, but I didn't quite like its formatting style. That plus pprint doesn't allow you to inspect objects like Data::Dumper does:

Searched on the net and came across these:

https://gist.github.com/1071857#file_dumper.pyamazon

>>> y = { 1: [1,2,3], 2: [{'a':1},{'b':2}]}

>>> pp = pprint.PrettyPrinter(indent = 4)
>>> pp.pprint(y)
{   1: [1, 2, 3], 2: [{   'a': 1}, {   'b': 2}]}

>>> print(Dumper.dump(y)) # Dumper is the python module in the above link
{
    1: [
        1 
        2 
        3
    ] 
    2: [
        {
            'a': 1
        } 
        {
            'b': 2
        }
    ]
}
>>> print(Dumper.dump(pp))
instance::pprint.PrettyPrinter
    __dict__ :: {
        '_depth': None 
        '_stream': file:: > 
        '_width': 80 
        '_indent_per_level': 4
    }

Also worth checking is http://salmon-protocol.googlecode.com/svn-history/r24/trunk/salmon-playground/dumper.py It has its own style and seems useful too.

4
votes

Here is a simple solution for dumping nested data made up of dictionaries, lists, or tuples (it works quite well for me):

Python2

def printStruct(struc, indent=0):
  if isinstance(struc, dict):
    print '  '*indent+'{'
    for key,val in struc.iteritems():
      if isinstance(val, (dict, list, tuple)):
        print '  '*(indent+1) + str(key) + '=> '
        printStruct(val, indent+2)
      else:
        print '  '*(indent+1) + str(key) + '=> ' + str(val)
    print '  '*indent+'}'
  elif isinstance(struc, list):
    print '  '*indent + '['
    for item in struc:
      printStruct(item, indent+1)
    print '  '*indent + ']'
  elif isinstance(struc, tuple):
    print '  '*indent + '('
    for item in struc:
      printStruct(item, indent+1)
    print '  '*indent + ')'
  else: print '  '*indent + str(struc)

Python3

 def printStruct(struc, indent=0):
   if isinstance(struc, dict):
     print ('  '*indent+'{')
     for key,val in struc.items():
       if isinstance(val, (dict, list, tuple)):
         print ('  '*(indent+1) + str(key) + '=> ')
         printStruct(val, indent+2)
       else:
         print ('  '*(indent+1) + str(key) + '=> ' + str(val))
     print ('  '*indent+'}')
   elif isinstance(struc, list):
     print ('  '*indent + '[')
     for item in struc:
       printStruct(item, indent+1)
     print ('  '*indent + ']')
   elif isinstance(struc, tuple):
     print ('  '*indent + '(')
     for item in struc:
       printStruct(item, indent+1)
     print ('  '*indent + ')')
   else: print ('  '*indent + str(struc))

See it at work:

>>> d = [{'a1':1, 'a2':2, 'a3':3}, [1,2,3], [{'b1':1, 'b2':2}, {'c1':1}], 'd1', 'd2', 'd3']
>>> printStruct(d)
[
  {
    a1=> 1
    a3=> 3
    a2=> 2
  }
  [
    1
    2
    3
  ]
  [
    {
      b1=> 1
      b2=> 2
    }
    {
      c1=> 1
    }
  ]
  d1
  d2
  d3
]
3
votes
  • For serialization, there are many options.

    • One of the best is JSON, which is a language-agnostic standard for serialization. It is available in 2.6 in the stdlib json module and before that with the same API in the third-party simplejson module.

    • You do not want to use marshal, which is fairly low-level. If you wanted what it provides, you would use pickle.

    • I avoid using pickle the format is Python-only and insecure. Deserializing using pickle can execute arbitrary code.

      • If you did use pickle, you want to use the C implementation thereof. (Do import cPickle as pickle.)
  • For debugging, you usually want to look at the object's repr or to use the pprint module.

1
votes

As far as inspecting your object goes, I found this a useful equivalent of Data:Dumper:

https://salmon-protocol.googlecode.com/svn-history/r24/trunk/salmon-playground/dumper.py

It can handle unicode strings.

1
votes

I needed to return Perl-like dump for API request so I came up with this which doesn't format the output to be pretty, but makes perfect job for me.

from decimal import Decimal
from datetime import datetime, date

def dump(self, obj):

    if obj is None:
        return "undef"

    if isinstance(obj, dict):
        return self.dump_dict(obj)

    if isinstance(obj, (list, tuple)):
        return self.dump_list(obj)

    if isinstance(obj, Decimal):
        return "'{:.05f}'".format(obj)
        # ... or handle it your way

    if isinstance(obj, (datetime, date)):
        return "'{}'".format(obj.isoformat(
            sep=' ',
            timespec='milliseconds'))
        # ... or handle it your way

    return "'{}'".format(obj)

def dump_dict(self, obj):
    result = []
    for key, val in obj.items():
        result.append(' => '.join((self.dump(key), self.dump(val))))

    return ' '.join(('{', ', '.join(result), '}'))

def dump_list(self, obj):
    result = []
    for val in obj:
        result.append(self.dump(val))

    return ' '.join(('[', ', '.join(result), ']'))



Using the above:

    example_dict = {'a': 'example1', 'b': 'example2', 'c': [1, 2, 3, 'asd'], 'd': [{'g': 'something1', 'e': 'something2'}, {'z': 'something1'}]}

    print(dump(example_dict))

will ouput:

    { 'b' => 'example2', 'a' => 'example1', 'd' => [ { 'g' => 'something1', 'e' => 'something2' }, { 'z' => 'something1' } ], 'c' => [ '1', '2', '3', 'asd' ] }
1
votes

If you want something that works better than pprint, but doesn't require rolling your own, try importing dumper from pypi:
https://github.com/jric/Dumper.py or https://github.com/ericholscher/pypi/blob/master/dumper.py

0
votes

Saw this and realized Python has something that works akin to Data::Dumper in Dumper. The author describes it as

Dump Python data structures (including class instances) in a nicely- nested, easy-to-read form. Handles recursive data structures properly, and has sensible options for limiting the extent of the dump both by simple depth and by some rules for how to handle contained instances.

Install it via pip. The Github repo is at https://github.com/jric/Dumper.py.

0
votes

Isn't it true that all the answers ignore dumping anything else than a combination of the basic data types like lists, dicts, etc.? I have just ran pprint on an Python Xlib Window object and got… <<class 'Xlib.display.Window'> 0x004001fe>… that's all. No data fields, no methods listed… Is there anything that does a real dump of an object? With e.g.: all its attributes?