Is there a Python equivalent to Perl's Data::D

2019-01-25 01:29发布

问题:

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!

回答1:

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.



回答2:

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



回答3:

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'}


回答4:

  • 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.



回答5:

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

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)

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
]


回答6:

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.



回答7:

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.



回答8:

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



回答9:

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' ] }