538

How can I pretty print a dictionary with depth of ~4 in Python? I tried pretty printing with pprint(), but it did not work:

import pprint 
pp = pprint.PrettyPrinter(indent=4)
pp.pprint(mydict)

I simply want an indentation ("\t") for each nesting, so that I get something like this:

key1
    value1
    value2
    key2
       value1
       value2

etc.

How can I do this?

martineau
  • 119,623
  • 25
  • 170
  • 301
  • 47
    What does "did not work" mean? Please specify very precisely how pprint "did not work". – S.Lott Jul 12 '10 at 14:43
  • 8
    I have now used 3 of these answers (each good in a specific scenario): [@Ken's json answer](http://stackoverflow.com/a/3314411/52074) is good but fails sometimes when the object can't be json serializable (throws exception). if @Ken's json answer doesn't work try [@Andy's yaml answer](http://stackoverflow.com/a/14892136/52074) and it should work but the string output is a little less human readable. [@sth's answer] is the most generic (should work for any object and doesn't use any libs). – Trevor Boyd Smith Nov 11 '16 at 19:43
  • I think you should try to find a proper the `width` parameter. Check out the [description](https://docs.python.org/3/library/pprint.html#pprint.PrettyPrinter) – Ersel Er Nov 06 '20 at 16:58
  • is it possible to get the string representation of the pretty printed string? i.e. I want the pretty printable string and thus don't want a solution that prints directly. – Charlie Parker Oct 24 '22 at 19:16
  • are you just missing the width=1 option? https://stackoverflow.com/a/75119001/1896134 – JayRizzo Jan 14 '23 at 15:26

30 Answers30

828

My first thought was that the JSON serializer is probably pretty good at nested dictionaries, so I'd cheat and use that:

>>> import json
>>> print(json.dumps({'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}},
...                  sort_keys=True, indent=4))
{
    "a": 2,
    "b": {
        "x": 3,
        "y": {
            "t1": 4,
            "t2": 5
        }
    }
}
Mike Pennington
  • 41,899
  • 19
  • 136
  • 174
Ken
  • 9,797
  • 3
  • 16
  • 14
  • 78
    This is cool, but doesn't print all dictionaries well. print json.dumps(myObject.__dict__, sort_keys=True, indent=4) #TypeError: is not JSON serializable – tponthieux Feb 08 '12 at 23:30
  • @RocketDonkey: It should work with almost any subclass of `dict`. I just tried it with my custom [`OrderedDefaultdict`](http://stackoverflow.com/a/4127426/355230) with no problems. – martineau May 24 '13 at 02:22
  • 12
    While this looks useful, it's output is not what the OP wanted. – martineau May 24 '13 at 03:28
  • 7
    @martineau: The OP's requested output doesn't make sense, dictionaries need keys per value. – naught101 Oct 02 '13 at 04:28
  • 3
    @naught101: A pretty printer can do whatever is needed to produce the output desired. – martineau Oct 02 '13 at 07:57
  • used pretty printer to produce this: `{ 0: { 0: { (0, 0): 1}}, 1: { 0: { (0, 1): 1, (1, 0): 1}}}`. `json.dumps` gave me: `TypeError: key (0, 0) is not a string` – juggler Jan 02 '14 at 21:10
  • 48
    json.dumps takes a conversion function as an optional argument, so with json.dumps(myObject.__dict__, sort_keys=True, indent=4, deault=str) you can at least use an objects implementation of __repr__ to print itself and get round the 'not JSON serializable' TypeError – RFairey Sep 23 '14 at 16:20
  • Using json is a neat trick but can work in all case, functions and ojects are translated into string using RFairey trick, dict key don't keep their type, and tuples are changed into lists. YOu can look at my solution for a result that corespond to original results of the python interpreter but pretty printed. – y.petremann Oct 06 '14 at 04:42
  • 1
    None gets printed as null, which also sucks. – John Jiang Feb 26 '21 at 06:18
  • Doesn't work if your dictionary contains binary values – quickinsights May 27 '22 at 18:46
  • 1
    @JohnJiang Worth pointing out that `True` becomes `true` and `False` becomes `false` as well. – Simply Beautiful Art Aug 28 '22 at 00:55
  • Types can not be printed with json.dumps as they have no JSON equivalent representation. It would help to improve quality, if you explain briefly how you cheat/what can not be handled. – Jay-Pi Oct 05 '22 at 10:37
  • is it possible to get the string representation of the pretty printed string? i.e. I want the pretty printable string and thus don't want a solution that prints directly. – Charlie Parker Oct 24 '22 at 19:16
  • @KarthikT it is not the default because it creates a json-string which can not be converted back into a python and that would be a terrible silent error in most situations where people use json. – julaine Apr 21 '23 at 07:44
  • Booleans are a problem with json.dumps() if you intent to read back the output as Python code, as json.dumps() prints out 'false' and 'true' instead of 'False' and 'True'. – Hans Deragon Aug 15 '23 at 17:54
218

I'm not sure how exactly you want the formatting to look like, but you could start with a function like this:

def pretty(d, indent=0):
   for key, value in d.items():
      print('\t' * indent + str(key))
      if isinstance(value, dict):
         pretty(value, indent+1)
      else:
         print('\t' * (indent+1) + str(value))
sth
  • 222,467
  • 53
  • 283
  • 367
  • 16
    U know @Ken's conventional answer is much better than this. Json already handles everything and this can give errors such: **UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in position 50: ordinal not in range(128)** – wonderwhy Aug 27 '14 at 13:20
  • I can't make it works with the nested dict of my solution, because it gave me a UnicodeEncodeError, also it don't print dict key, don't go inside list and tuples and don't keep a python valid syntax. – y.petremann Oct 06 '14 at 04:33
  • This answer worked like a charm for me, however I posted a new question https://stackoverflow.com/questions/36972225/pretty-print-nested-dictionary-with-a-limit which sets a limit to how many values should be printed. – gsamaras May 01 '16 at 21:34
  • Pretty good. If you've got nested lists like in the OP's question, you need to add some handling for that. If you're having issues in Py2, it's cause it can't handle Unicode properly without hacks like `__future__` that the answer now mentions, so you have to employ those wherever needed (or update to 3 already). – sudo Feb 14 '18 at 18:10
  • 2
    This worked well enough for me : ```python def pretty(d, indent=0): for key, value in d.items(): if isinstance(value, dict): print(' ' * indent + str(key)) pretty(value, indent+1) else: print(' ' * (indent+1) + f"{key}: {value}") ``` – hum3 Apr 27 '20 at 11:13
  • 1
    @gsamaras If one wishes to limit the amount of output for readability, consider using [IPython](https://stackoverflow.com/a/71674057) or my [prettyformatter](https://stackoverflow.com/a/73515283). – Simply Beautiful Art Aug 28 '22 at 00:53
  • This does not show how to handle types in a nice way, but does the job. – Jay-Pi Oct 05 '22 at 10:40
  • is it possible to get the string representation of the pretty printed string? i.e. I want the pretty printable string and thus don't want a solution that prints directly. – Charlie Parker Oct 24 '22 at 19:16
  • 5
    @wonderwhy "Json already handles everything" It most certainly doesn't e.g. `dumps({(2, 4): 3}, indent=2)` gives "TypeError: keys must be str, int, float, bool or None, not tuple". Or `dumps({3: 3}, indent=2)` does produce an output but it incorrectly prints the key as a string. And that's before getting onto other data types e.g. datetime – Arthur Tacca Jan 10 '23 at 10:51
109

You could try YAML via PyYAML. Its output can be fine-tuned. I'd suggest starting with the following:

print(yaml.dump(data, allow_unicode=True, default_flow_style=False))

The result is very readable; it can be also parsed back to Python if needed.

Edit:

Example:

>>> import yaml
>>> data = {'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}}
>>> print(yaml.dump(data, default_flow_style=False))
a: 2
b:
  x: 3
  y:
    t1: 4
    t2: 5
JayRizzo
  • 3,234
  • 3
  • 33
  • 49
Andy Mikhailenko
  • 1,571
  • 1
  • 11
  • 10
  • 2
    Using yaml is very interesting because it keep data type over it's format, the only thing I can say against it is that it don't produce a valid python string, but can almost be converted back in python. – y.petremann Oct 06 '14 at 04:49
  • 2
    yaml doesn't like Numpy's version of scalar types... I wasn't surprised that is doesn't support numpy arrays, but I would have expected the same output for a `float` and a `numpy.float64` – PhilMacKay Mar 02 '17 at 17:12
  • 1
    this approach also worked for me using a list of dictionaries – Grant Shannon Feb 18 '20 at 08:18
  • is it possible to get the string representation of the pretty printed string? i.e. I want the pretty printable string and thus don't want a solution that prints directly. – Charlie Parker Oct 24 '22 at 19:17
  • @CharlieParker just don't call `print()`? – Andy Mikhailenko Jan 23 '23 at 12:50
93

One of the most pythonic ways for that is to use the already build pprint module.

The argument that you need for define the print depth is as you may expect depth

import pprint
pp = pprint.PrettyPrinter(depth=4)
pp.pprint(mydict)

That's it !

Juan-Kabbali
  • 1,961
  • 15
  • 20
  • @CharlieParker, if you click on the link to the documentation in above answer, you will see that there is also a method `pprint.pformat()`. – wovano Oct 25 '22 at 06:37
  • 2
    I don't think this does what OP asked, or at least isn't working for me: `>>> pprint.PrettyPrinter(depth=4).pprint({'a': 2, 'b': {'x': 3, 'y': {'t1': 4, 't2': 5}}})` results in `{'a': 2, 'b': {'x': 3, 'y': {'t1': 4, 't2': 5}}}` (all one line) – jjj Jul 12 '23 at 14:55
91

By this way you can print it in pretty way for example your dictionary name is yasin

import json

print (json.dumps(yasin, indent=2))

or, safer:

print (json.dumps(yasin, indent=2, default=str))
mike rodent
  • 14,126
  • 11
  • 103
  • 157
yasin lachini
  • 5,188
  • 6
  • 33
  • 56
  • 18
    This assumes the content of the dictionary is json serialize-able, which is necessarily not true. – SpiXel Oct 07 '19 at 11:20
  • 5
    @SpiXel. I like Juan-Kabbali's answer ... but just to answer your point, one can go: `print (json.dumps(yasin, indent=2, default=str))` : anything "hairy" is then handled with the `str` function. – mike rodent Feb 10 '21 at 18:11
  • is it possible to get the string representation of the pretty printed string? i.e. I want the pretty printable string and thus don't want a solution that prints directly. – Charlie Parker Oct 24 '22 at 19:17
48

As of what have been done, I don't see any pretty printer that at least mimics the output of the python interpreter with very simple formatting so here's mine :

class Formatter(object):
    def __init__(self):
        self.types = {}
        self.htchar = '\t'
        self.lfchar = '\n'
        self.indent = 0
        self.set_formater(object, self.__class__.format_object)
        self.set_formater(dict, self.__class__.format_dict)
        self.set_formater(list, self.__class__.format_list)
        self.set_formater(tuple, self.__class__.format_tuple)

    def set_formater(self, obj, callback):
        self.types[obj] = callback

    def __call__(self, value, **args):
        for key in args:
            setattr(self, key, args[key])
        formater = self.types[type(value) if type(value) in self.types else object]
        return formater(self, value, self.indent)

    def format_object(self, value, indent):
        return repr(value)

    def format_dict(self, value, indent):
        items = [
            self.lfchar + self.htchar * (indent + 1) + repr(key) + ': ' +
            (self.types[type(value[key]) if type(value[key]) in self.types else object])(self, value[key], indent + 1)
            for key in value
        ]
        return '{%s}' % (','.join(items) + self.lfchar + self.htchar * indent)

    def format_list(self, value, indent):
        items = [
            self.lfchar + self.htchar * (indent + 1) + (self.types[type(item) if type(item) in self.types else object])(self, item, indent + 1)
            for item in value
        ]
        return '[%s]' % (','.join(items) + self.lfchar + self.htchar * indent)

    def format_tuple(self, value, indent):
        items = [
            self.lfchar + self.htchar * (indent + 1) + (self.types[type(item) if type(item) in self.types else object])(self, item, indent + 1)
            for item in value
        ]
        return '(%s)' % (','.join(items) + self.lfchar + self.htchar * indent)

To initialize it :

pretty = Formatter()

It can support the addition of formatters for defined types, you simply need to make a function for that like this one and bind it to the type you want with set_formater :

from collections import OrderedDict

def format_ordereddict(self, value, indent):
    items = [
        self.lfchar + self.htchar * (indent + 1) +
        "(" + repr(key) + ', ' + (self.types[
            type(value[key]) if type(value[key]) in self.types else object
        ])(self, value[key], indent + 1) + ")"
        for key in value
    ]
    return 'OrderedDict([%s])' % (','.join(items) +
           self.lfchar + self.htchar * indent)
pretty.set_formater(OrderedDict, format_ordereddict)

For historical reasons, I keep the previous pretty printer which was a function instead of a class, but they both can be used the same way, the class version simply permit much more :

def pretty(value, htchar='\t', lfchar='\n', indent=0):
    nlch = lfchar + htchar * (indent + 1)
    if type(value) is dict:
        items = [
            nlch + repr(key) + ': ' + pretty(value[key], htchar, lfchar, indent + 1)
            for key in value
        ]
        return '{%s}' % (','.join(items) + lfchar + htchar * indent)
    elif type(value) is list:
        items = [
            nlch + pretty(item, htchar, lfchar, indent + 1)
            for item in value
        ]
        return '[%s]' % (','.join(items) + lfchar + htchar * indent)
    elif type(value) is tuple:
        items = [
            nlch + pretty(item, htchar, lfchar, indent + 1)
            for item in value
        ]
        return '(%s)' % (','.join(items) + lfchar + htchar * indent)
    else:
        return repr(value)

To use it :

>>> a = {'list':['a','b',1,2],'dict':{'a':1,2:'b'},'tuple':('a','b',1,2),'function':pretty,'unicode':u'\xa7',("tuple","key"):"valid"}
>>> a
{'function': <function pretty at 0x7fdf555809b0>, 'tuple': ('a', 'b', 1, 2), 'list': ['a', 'b', 1, 2], 'dict': {'a': 1, 2: 'b'}, 'unicode': u'\xa7', ('tuple', 'key'): 'valid'}
>>> print(pretty(a))
{
    'function': <function pretty at 0x7fdf555809b0>,
    'tuple': (
        'a',
        'b',
        1,
        2
    ),
    'list': [
        'a',
        'b',
        1,
        2
    ],
    'dict': {
        'a': 1,
        2: 'b'
    },
    'unicode': u'\xa7',
    ('tuple', 'key'): 'valid'
}

Compared to other versions :

  • This solution looks directly for object type, so you can pretty print almost everything, not only list or dict.
  • Doesn't have any dependancy.
  • Everything is put inside a string, so you can do whatever you want with it.
  • The class and the function has been tested and works with Python 2.7 and 3.4.
  • You can have all type of objects inside, this is their representations and not theirs contents that being put in the result (so string have quotes, Unicode string are fully represented ...).
  • With the class version, you can add formatting for every object type you want or change them for already defined ones.
  • key can be of any valid type.
  • Indent and Newline character can be changed for everything we'd like.
  • Dict, List and Tuples are pretty printed.
y.petremann
  • 2,702
  • 1
  • 15
  • 19
  • 4
    This should definitely be the accepted solution - the lack of a dependency on JSON is huge. – Josh Nov 13 '14 at 15:43
  • it would be cool if it could do objects by converting them to dicts and setting their key to be the object type – Alex Cory Sep 22 '16 at 04:37
  • You can basically replace the format_object method internaly or externaly to do that. – y.petremann Sep 23 '16 at 17:45
  • 2
    set_formater - need two t, this is a typo, should be formatter – Nikolay Prokopyev Jun 26 '19 at 18:06
  • @AlexCory Inspired by this idea, I ended up implementing it in my [prettyformatter](https://stackoverflow.com/a/73515283), which allows one to easily add pretty formatting for custom classes as well as JSON serialize them into lists and/or dictionaries. – Simply Beautiful Art Aug 28 '22 at 05:18
  • @Josh json is in the standard library. Why would it be a huge problem to depend on it? – julaine Apr 21 '23 at 08:06
20

The modern solution here is to use rich. Install with

pip install rich

and use as

from rich import print

d = {
    "Alabama": "Montgomery",
    "Alaska": "Juneau",
    "Arizona": "Phoenix",
    "Arkansas": "Little Rock",
    "California": "Sacramento",
    "Colorado": "Denver",
    "Connecticut": "Hartford",
    "Delaware": "Dover",
    "Florida": "Tallahassee",
    "Georgia": "Atlanta",
    "Hawaii": "Honolulu",
    "Idaho": "Boise",
}
print(d)

The output is nicely indented:

enter image description here

Nico Schlömer
  • 53,797
  • 27
  • 201
  • 249
  • Tried a few different things with pprint and json.dumps that didn't work out but this worked great! – Christian Wilkie Oct 10 '21 at 19:47
  • 1
    Unless I am missing something, this is good *only* if you want to print to console, but not if logging to a log file since it's whole function is to *print*. Would be nice if this lib actually returned a value that could be used. – Eitel Dagnin Mar 11 '22 at 10:34
  • The documentation for Rich { https://github.com/Textualize/rich#rich-print } says that it will work with terminals and Jupyter Notebooks too. @EitelDagnin you are asking for a formatter, not just a "pretty printer" like the OP asked for. – Rich Lysakowski PhD Apr 22 '22 at 11:22
17

I had to pass the default parameter as well, like this:

print(json.dumps(my_dictionary, indent=4, default=str))

and if you want the keys sorted, then you can do:

print(json.dumps(my_dictionary, sort_keys=True, indent=4, default=str))

in order to fix this type error:

TypeError: Object of type 'datetime' is not JSON serializable

which caused by datetimes being some values in the dictionary.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • That only gets applied to the values, not the keys. A dict with Tuples as keys will still raise a type error. – julaine Apr 21 '23 at 14:53
14

Another option with yapf:

from pprint import pformat
from yapf.yapflib.yapf_api import FormatCode

dict_example = {'1': '1', '2': '2', '3': [1, 2, 3, 4, 5], '4': {'1': '1', '2': '2', '3': [1, 2, 3, 4, 5]}}
dict_string = pformat(dict_example)
formatted_code, _ = FormatCode(dict_string)

print(formatted_code)

Output:

{
    '1': '1',
    '2': '2',
    '3': [1, 2, 3, 4, 5],
    '4': {
        '1': '1',
        '2': '2',
        '3': [1, 2, 3, 4, 5]
    }
}
Eyal Levin
  • 16,271
  • 6
  • 66
  • 56
  • This solution assumes that `yapf` installed by default, which is not. you can install it `pip install yapf`. If you are using conda `conda install yapf` – Medhat Oct 05 '20 at 22:12
  • 1
    Very useful when you have non JSON keys in your dictionary, like tuples. – Danilo Gómez Mar 23 '21 at 13:50
  • Why use `pformat` to serialize a dictionary when you can use `repr`? Since `yafp` is actually the formatter, and it only needs a string. – Danilo Gómez Mar 23 '21 at 13:52
7

You can use print-dict

from print_dict import pd

dict1 = {
    'key': 'value'
} 

pd(dict1)

Output:

{
    'key': 'value'
}

Output of this Python code:

{
    'one': 'value-one',
    'two': 'value-two',
    'three': 'value-three',
    'four': {
        '1': '1',
        '2': '2',
        '3': [1, 2, 3, 4, 5],
        '4': {
            'method': <function custom_method at 0x7ff6ecd03e18>,
            'tuple': (1, 2),
            'unicode': '✓',
            'ten': 'value-ten',
            'eleven': 'value-eleven',
            '3': [1, 2, 3, 4]
        }
    },
    'object1': <__main__.Object1 object at 0x7ff6ecc588d0>,
    'object2': <Object2 info>,
    'class': <class '__main__.Object1'>
}

Install:

$ pip install print-dict

Disclosure: I'm the author of print-dict

Eyal Levin
  • 16,271
  • 6
  • 66
  • 56
  • 2
    This is the easiest solution. Works great for large dictionaries with a lot of nested keys. – Nairum Aug 24 '20 at 14:43
6

As others have posted, you can use recursion/dfs to print the nested dictionary data and call recursively if it is a dictionary; otherwise print the data.

def print_json(data):
    if type(data) == dict:
            for k, v in data.items():
                    print k
                    print_json(v)
    else:
            print data
Brad Solomon
  • 38,521
  • 31
  • 149
  • 235
6

pout can pretty print anything you throw at it, for example (borrowing data from another answer):

data = {'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}}
pout.vs(data)

would result in output printed to the screen like:

{
    'a': 2,
    'b':
    {
        'y':
        {
            't2': 5,
            't1': 4
        },
        'x': 3
    }
}

or you can return the formatted string output of your object:

v = pout.s(data)

Its primary use case is for debugging so it doesn't choke on object instances or anything and it handles unicode output as you would expect, works in python 2.7 and 3.

disclosure: I'm the author and maintainer of pout.

Jaymon
  • 5,363
  • 3
  • 34
  • 34
  • Doesn't work on windows unfortunately, would be nice if you showed supported systems clearly – Mandera Nov 11 '20 at 17:24
  • @Mandera If you could open an issue at https://github.com/Jaymon/pout/issues with details since I can't think of any reason why it wouldn't work on Windows, we can continue the conversation there – Jaymon Nov 11 '20 at 23:09
  • Oh sure thing! My mistake assuming you weren't trying to support it – Mandera Nov 12 '20 at 06:35
5

prettyformatter

Disclaimer: I'm the author of the package.

For a comparison with other formatters, see Other Formatters.


Formatting

Unlike pprint.pprint, prettyformatter spreads vertically more and attempts to align items more.

Unlike json.dumps, prettyformatter is usually more compact and attempts to align dictionary values wherever reasonable.

from prettyformatter import pprint

batters = [
    {"id": "1001", "type": "Regular"},
    {"id": "1002", "type": "Chocolate"},
    {"id": "1003", "type": "Blueberry"},
    {"id": "1004", "type": "Devil's Food"},
]

toppings = [
    {"id": "5001", "type": None},
    {"id": "5002", "type": "Glazed"},
    {"id": "5005", "type": "Sugar"},
    {"id": "5007", "type": "Powdered Sugar"},
    {"id": "5006", "type": "Chocolate with Sprinkles"},
    {"id": "5003", "type": "Chocolate"},
    {"id": "5004", "type": "Maple"},
]

data = {"id": "0001", "type": "donut", "name": "Cake", "ppu": 0.55, "batters": batters, "topping": toppings}

pprint(data)

Output:

{
    "id"    : "0001",
    "type"  : "donut",
    "name"  : "Cake",
    "ppu"   : 0.55,
    "batters":
        [
            {"id": "1001", "type": "Regular"},
            {"id": "1002", "type": "Chocolate"},
            {"id": "1003", "type": "Blueberry"},
            {"id": "1004", "type": "Devil's Food"},
        ],
    "topping":
        [
            {"id": "5001", "type": None},
            {"id": "5002", "type": "Glazed"},
            {"id": "5005", "type": "Sugar"},
            {"id": "5007", "type": "Powdered Sugar"},
            {"id": "5006", "type": "Chocolate with Sprinkles"},
            {"id": "5003", "type": "Chocolate"},
            {"id": "5004", "type": "Maple"},
        ],
}

Features

See here for the full documentation.

JSON

Unlike pprint.pprint, prettyformatter supports JSON conversion via the json=True argument. This includes changing None to null, True to true, False to false, and correct use of quotes.

Unlike json.dumps, prettyformatter supports JSON coercion with more data types. This includes changing any dataclass or mapping into a dict and any iterable into a list.

from dataclasses import dataclass

from prettyformatter import PrettyDataclass, pprint


@dataclass(unsafe_hash=True)
class Point(PrettyDataclass):
    x: int
    y: int


pprint((Point(1, 2), Point(3, 4)), json=True)

Output:

[{"x": 1, "y": 2}, {"x": 3, "y": 4}]

Customization

Unlike pprint.pprint or json.dumps, prettyformatter supports easy customization with additional types.

Implementing the __pargs__ and/or __pkwargs__ methods for a prettyformatter.PrettyClass subclass allows one to easily customize classes in the form of "cls_name(*args, **kwargs)".

from prettyformatter import PrettyClass


class Dog(PrettyClass):

    def __init__(self, name, **kwargs):
        self.name = name

    def __pkwargs__(self):
        return {"name": self.name}


print(Dog("Fido"))
"""
Dog(name="Fido")
"""

print(Dog("Fido"), json=True)
"""
{"name": "Fido"}
"""

Implementing the __pformat__ method allows even more specific implementations of the pformat function.

Implementing the @prettyformatter.register function also allows customizing classes that already exist in the same way implementing __pformat__ would.

import numpy as np
from prettyformatter import pprint, register

@register(np.ndarray)
def pformat_ndarray(obj, specifier, depth, indent, shorten, json):
    if json:
        return pformat(obj.tolist(), specifier, depth, indent, shorten, json)
    with np.printoptions(formatter=dict(all=lambda x: format(x, specifier))):
        return repr(obj).replace("\n", "\n" + " " * depth)

pprint(dict.fromkeys("ABC", np.arange(9).reshape(3, 3)))

Output:

{
    "A":
        array([[0, 1, 2],
               [3, 4, 5],
               [6, 7, 8]]),
    "B":
        array([[0, 1, 2],
               [3, 4, 5],
               [6, 7, 8]]),
    "C":
        array([[0, 1, 2],
               [3, 4, 5],
               [6, 7, 8]]),
}
Simply Beautiful Art
  • 1,284
  • 15
  • 16
4

I took sth's answer and modified it slightly to fit my needs of a nested dictionaries and lists:

def pretty(d, indent=0):
    if isinstance(d, dict):
        for key, value in d.iteritems():
            print '\t' * indent + str(key)
            if isinstance(value, dict) or isinstance(value, list):
                pretty(value, indent+1)
            else:
                print '\t' * (indent+1) + str(value)
    elif isinstance(d, list):
        for item in d:
            if isinstance(item, dict) or isinstance(item, list):
                pretty(item, indent+1)
            else:
                print '\t' * (indent+1) + str(item)
    else:
        pass

Which then gives me output like:

>>> 
xs:schema
    @xmlns:xs
        http://www.w3.org/2001/XMLSchema
    xs:redefine
        @schemaLocation
            base.xsd
        xs:complexType
            @name
                Extension
            xs:complexContent
                xs:restriction
                    @base
                        Extension
                    xs:sequence
                        xs:element
                            @name
                                Policy
                            @minOccurs
                                1
                            xs:complexType
                                xs:sequence
                                    xs:element
                                            ...
Community
  • 1
  • 1
MuffintopBikini
  • 1,042
  • 7
  • 11
3

I used what you guys taught me plus the power of decorators to overload the classic print function. Just change the indent to your needs. I added it as a gist in github in case you want to star(save) it.

def print_decorator(func):
    """
    Overload Print function to pretty print Dictionaries 
    """
    def wrapped_func(*args,**kwargs):
        if isinstance(*args, dict):
            return func(json.dumps(*args, sort_keys=True, indent=2, default=str))
        else:
            return func(*args,**kwargs)
    return wrapped_func
print = print_decorator(print)

Now just use print as usual.

  • 2
    Note: works only in Python 3, because in Python 2, `print` is a keyword and since cannot be assigned to. – TheEagle Jun 22 '21 at 22:57
2

I wrote this simple code to print the general structure of a json object in Python.

def getstructure(data, tab = 0):
    if type(data) is dict:
        print ' '*tab + '{' 
        for key in data:
            print ' '*tab + '  ' + key + ':'
            getstructure(data[key], tab+4)
        print ' '*tab + '}'         
    elif type(data) is list and len(data) > 0:
        print ' '*tab + '['
        getstructure(data[0], tab+4)
        print ' '*tab + '  ...'
        print ' '*tab + ']'

the result for the following data

a = {'list':['a','b',1,2],'dict':{'a':1,2:'b'},'tuple':('a','b',1,2),'function':'p','unicode':u'\xa7',("tuple","key"):"valid"}
getstructure(a)

is very compact and looks like this:

{
  function:
  tuple:
  list:
    [
      ...
    ]
  dict:
    {
      a:
      2:
    }
  unicode:
  ('tuple', 'key'):
}
Abtin Rasoulian
  • 869
  • 1
  • 8
  • 11
2

I'm just returning to this question after taking sth's answer and making a small but very useful modification. This function prints all keys in the JSON tree as well as the size of leaf nodes in that tree.

def print_JSON_tree(d, indent=0):
    for key, value in d.iteritems():
        print '    ' * indent + unicode(key),
        if isinstance(value, dict):
            print; print_JSON_tree(value, indent+1)
        else:
            print ":", str(type(d[key])).split("'")[1], "-", str(len(unicode(d[key])))

It's really nice when you have large JSON objects and want to figure out where the meat is. Example:

>>> print_JSON_tree(JSON_object)
key1
    value1 : int - 5
    value2 : str - 16
    key2
       value1 : str - 34
       value2 : list - 5623456

This would tell you that most of the data you care about is probably inside JSON_object['key1']['key2']['value2'] because the length of that value formatted as a string is very large.

Ulf Aslak
  • 7,876
  • 4
  • 34
  • 56
2

I tried the following and got my desired results

Method 1: Step 1: Install print_dict by typing the following command in cmd

pip install print_dict

Step 2: Import print_dict as

from print_dict import pd

Step 3: Printing using pd

pd(your_dictionary_name)

Example Output:

{
    'Name': 'Arham Rumi',
    'Age': 21,
    'Movies': ['adas', 'adfas', 'fgfg', 'gfgf', 'vbxbv'],
    'Songs': ['sdfsd', 'dfdgfddf', 'dsdfd', 'sddfsd', 'sdfdsdf']
}

Method 2: We can also use for loop to print the dictionary using items method

for key, Value in your_dictionary_name.items():
    print(f"{key} : {Value}")
ARHAM RUMI
  • 441
  • 5
  • 11
  • Method 2 here is one of the best I have seen on this SO post, because it is core Python 3 only, no JSON imports. With a little bit of dynamic formatting, this could print nice-looking tabular nested outputs. – Rich Lysakowski PhD Apr 22 '22 at 11:01
2

The easiest is to install IPython and use something like below

from IPython.lib.pretty import pretty


class MyClass:
    __repr__(self):
       return pretty(data)  # replace data with what makes sense

In your case

print(pretty(mydict))
Pithikos
  • 18,827
  • 15
  • 113
  • 136
1

Sth, i sink that's pretty ;)

def pretty(d, indent=0):
    for key, value in d.iteritems():
        if isinstance(value, dict):
            print '\t' * indent + (("%30s: {\n") % str(key).upper())
            pretty(value, indent+1)
            print '\t' * indent + ' ' * 32 + ('} # end of %s #\n' % str(key).upper())
        elif isinstance(value, list):
            for val in value:
                print '\t' * indent + (("%30s: [\n") % str(key).upper())
                pretty(val, indent+1)
                print '\t' * indent + ' ' * 32 + ('] # end of %s #\n' % str(key).upper())
        else:
            print '\t' * indent + (("%30s: %s") % (str(key).upper(),str(value)))
VindeX
  • 35
  • 2
  • 2
    -1: Doesn't handle `list` values that aren't `dict` instances, i.e. `pretty({'key': [1, 2, 3]}, indent=4)` ==> `AttributeError: 'int' object has no attribute 'iteritems'`. I also don't like it uppercasing keys. – martineau May 24 '13 at 02:36
  • Your solution consider that there can't be a dict inside a list inside the root dict. Also it consider that we don't want to prettyprint a list or a tuple. Finally don't capitalize keys, the result for {'a':0,'A':1} would not be correct. – y.petremann Nov 22 '14 at 11:07
1
This class prints out a complex nested dictionary with sub dictionaries and sub lists.  
##
## Recursive class to parse and print complex nested dictionary
##

class NestedDictionary(object):
    def __init__(self,value):
        self.value=value

    def print(self,depth):
        spacer="--------------------"
        if type(self.value)==type(dict()):
            for kk, vv in self.value.items():
                if (type(vv)==type(dict())):
                    print(spacer[:depth],kk)
                    vvv=(NestedDictionary(vv))
                    depth=depth+3
                    vvv.print(depth)
                    depth=depth-3
                else:
                    if (type(vv)==type(list())):
                        for i in vv:
                            vvv=(NestedDictionary(i))
                            depth=depth+3
                            vvv.print(depth)
                            depth=depth-3
                    else:
                        print(spacer[:depth],kk,vv) 

##
## Instatiate and execute - this prints complex nested dictionaries
## with sub dictionaries and sub lists
## 'something' is a complex nested dictionary

MyNest=NestedDictionary(weather_com_result)
MyNest.print(0)
Derek Adair
  • 21,846
  • 31
  • 97
  • 134
1

Late, but an answer that does not require any additional libraries. Similar to STH's answer, but a little more robust in formatting and returns a full string that can then be printed:

def pretty_print_dict(
        input_dictionary,
        indent=1,
        depth=0
):
    # Bool flag to add comma's after first item in dict.
    needs_comma = False
    # String for any dict will start with a '{'
    return_string = '\t' * depth + '{\n'
    # Iterate over keys and values, building the full string out.
    for key, value in input_dictionary.items():
        # Start with key. If key follows a previous item, add comma.
        if needs_comma:
            return_string = return_string + ',\n' + '\t' * (depth + 1) + str(key) + ': '
        else:
            return_string = return_string + '\t' * (depth + 1) + str(key) + ': '
        # If the value is a dict, recursively call function.
        if isinstance(value, dict):
            return_string = return_string + '\n' + pretty_print_dict(value, depth=depth+2)
        else:
            return_string = return_string + '\t' * indent + str(value)
        # After first line, flip bool to True to make sure commas make it.
        needs_comma = True
    # Complete the dict with a '}'
    return_string = return_string + '\n' + '\t' * depth + '}'
    # Return dict string.
    return return_string

Let's see how it handles a dict like test_dict={1: 2, 3: {4: {5: 6}, 7: 8}, 9: 10}.

The string looks like: '{\n\t1: \t2,\n\t3: \n\t\t{\n\t\t\t4: \n\t\t\t\t{\n\t\t\t\t\t5: \t6\n\t\t\t\t},\n\t\t\t7: \t8\n\t\t},\n\t9: \t10\n}'.

Printing that string yields:

{
    1:  2,
    3: 
        {
            4: 
                {
                    5:  6
                },
            7:  8
        },
    9:  10
}
zurcam
  • 61
  • 5
1

There are so many nice implementations here, it made me want to add my own :). I used it for debugging in CircuitPython and MicroPython where json.dumps does not allow using the indent parameter, and pprint is not available as well.

It is implemented with self so can be dropped in into a class, and for each data it is showing the data type, which I find very useful for debugging. Not dependent on any external module.

def pretty_print_dict(self, d, indent=0):
    INDENT = 2
    if isinstance(d, dict):
        print(' ' * indent + '{')
        for key, value in d.items():
            print(f'{" " * (indent + INDENT)}{key}:')
            self.pretty_print_dict(value, indent + 2 * INDENT)
        print(' ' * indent + '}')
    elif isinstance(d, list):
        print(' ' * indent + '[')
        for item in d:
            self.pretty_print_dict(item, indent + INDENT)
        print(' ' * indent + ']')
    elif isinstance(d, str):
        print(' ' * indent + '<s>' + d + '</s>')
    elif isinstance(d, int):
        print(' ' * indent + '<i>' + str(d) + '</i>')
    elif isinstance(d, bool):
        print(' ' * indent + '<b>' + str(d) + '</b>')
    elif isinstance(d, float):
        print(' ' * indent + '<f>' + str(d) + '</f>')
    else:
        print(' ' * indent + '<?>' + str(d) + '</?>')

Usage: self.pretty_print_dict(my_dict)

ishahak
  • 6,585
  • 5
  • 38
  • 56
0

Here's a function I wrote based on what sth's comment. It's works the same as json.dumps with indent, but I'm using tabs instead of space for indents. In Python 3.2+ you can specify indent to be a '\t' directly, but not in 2.7.

def pretty_dict(d):
    def pretty(d, indent):
        for i, (key, value) in enumerate(d.iteritems()):
            if isinstance(value, dict):
                print '{0}"{1}": {{'.format( '\t' * indent, str(key))
                pretty(value, indent+1)
                if i == len(d)-1:
                    print '{0}}}'.format( '\t' * indent)
                else:
                    print '{0}}},'.format( '\t' * indent)
            else:
                if i == len(d)-1:
                    print '{0}"{1}": "{2}"'.format( '\t' * indent, str(key), value)
                else:
                    print '{0}"{1}": "{2}",'.format( '\t' * indent, str(key), value)
    print '{'
    pretty(d,indent=1)
    print '}'

Ex:

>>> dict_var = {'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}}
>>> pretty_dict(dict_var)
{
    "a": "2",
    "b": {
        "y": {
            "t2": "5",
            "t1": "4"
        },
        "x": "3"
    }
}
Al Conrad
  • 1,528
  • 18
  • 12
  • I can't make it works with the nested dict of my solution, because it gave me a UnicodeEncodeError, also items and keys are all converted in strings, what if we use numbers or tuples that contains lists and dicts ? Finnaly your solution take in account that our object we want to pretty print must be a dict. – y.petremann Oct 06 '14 at 04:26
  • I was not trying to write a generic print function for a python dict. The top rated comments already demonstrate how to pretty print a dict. My contribution was to write an alternative to json.dumps with '\t' for indenting instead of tabs in python 2.7. – Al Conrad Oct 08 '14 at 18:47
  • I agree with you about writing an alternative to json.dumps, for me the same problems as of json.dumps applies. Also, you could use a simple regex to change the indentation type, making your code simplier. – y.petremann Oct 08 '14 at 21:46
0

From this link:

def prnDict(aDict, br='\n', html=0,
            keyAlign='l',   sortKey=0,
            keyPrefix='',   keySuffix='',
            valuePrefix='', valueSuffix='',
            leftMargin=0,   indent=1 ):
    '''
return a string representive of aDict in the following format:
    {
     key1: value1,
     key2: value2,
     ...
     }

Spaces will be added to the keys to make them have same width.

sortKey: set to 1 if want keys sorted;
keyAlign: either 'l' or 'r', for left, right align, respectively.
keyPrefix, keySuffix, valuePrefix, valueSuffix: The prefix and
   suffix to wrap the keys or values. Good for formatting them
   for html document(for example, keyPrefix='<b>', keySuffix='</b>'). 
   Note: The keys will be padded with spaces to have them
         equally-wide. The pre- and suffix will be added OUTSIDE
         the entire width.
html: if set to 1, all spaces will be replaced with '&nbsp;', and
      the entire output will be wrapped with '<code>' and '</code>'.
br: determine the carriage return. If html, it is suggested to set
    br to '<br>'. If you want the html source code eazy to read,
    set br to '<br>\n'

version: 04b52
author : Runsun Pan
require: odict() # an ordered dict, if you want the keys sorted.
         Dave Benjamin 
         http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/161403
    '''

    if aDict:

        #------------------------------ sort key
        if sortKey:
            dic = aDict.copy()
            keys = dic.keys()
            keys.sort()
            aDict = odict()
            for k in keys:
                aDict[k] = dic[k]

        #------------------- wrap keys with ' ' (quotes) if str
        tmp = ['{']
        ks = [type(x)==str and "'%s'"%x or x for x in aDict.keys()]

        #------------------- wrap values with ' ' (quotes) if str
        vs = [type(x)==str and "'%s'"%x or x for x in aDict.values()] 

        maxKeyLen = max([len(str(x)) for x in ks])

        for i in range(len(ks)):

            #-------------------------- Adjust key width
            k = {1            : str(ks[i]).ljust(maxKeyLen),
                 keyAlign=='r': str(ks[i]).rjust(maxKeyLen) }[1]

            v = vs[i]        
            tmp.append(' '* indent+ '%s%s%s:%s%s%s,' %(
                        keyPrefix, k, keySuffix,
                        valuePrefix,v,valueSuffix))

        tmp[-1] = tmp[-1][:-1] # remove the ',' in the last item
        tmp.append('}')

        if leftMargin:
          tmp = [ ' '*leftMargin + x for x in tmp ]

        if html:
            return '<code>%s</code>' %br.join(tmp).replace(' ','&nbsp;')
        else:
            return br.join(tmp)     
    else:
        return '{}'

'''
Example:

>>> a={'C': 2, 'B': 1, 'E': 4, (3, 5): 0}

>>> print prnDict(a)
{
 'C'   :2,
 'B'   :1,
 'E'   :4,
 (3, 5):0
}

>>> print prnDict(a, sortKey=1)
{
 'B'   :1,
 'C'   :2,
 'E'   :4,
 (3, 5):0
}

>>> print prnDict(a, keyPrefix="<b>", keySuffix="</b>")
{
 <b>'C'   </b>:2,
 <b>'B'   </b>:1,
 <b>'E'   </b>:4,
 <b>(3, 5)</b>:0
}

>>> print prnDict(a, html=1)
<code>{
&nbsp;'C'&nbsp;&nbsp;&nbsp;:2,
&nbsp;'B'&nbsp;&nbsp;&nbsp;:1,
&nbsp;'E'&nbsp;&nbsp;&nbsp;:4,
&nbsp;(3,&nbsp;5):0
}</code>

>>> b={'car': [6, 6, 12], 'about': [15, 9, 6], 'bookKeeper': [9, 9, 15]}

>>> print prnDict(b, sortKey=1)
{
 'about'     :[15, 9, 6],
 'bookKeeper':[9, 9, 15],
 'car'       :[6, 6, 12]
}

>>> print prnDict(b, keyAlign="r")
{
        'car':[6, 6, 12],
      'about':[15, 9, 6],
 'bookKeeper':[9, 9, 15]
}
'''
Nathaniel Ford
  • 20,545
  • 20
  • 91
  • 102
user2757572
  • 463
  • 1
  • 4
  • 9
0

I'm a relative python newbie myself but I've been working with nested dictionaries for the past couple weeks and this is what I had came up with.

You should try using a stack. Make the keys from the root dictionary into a list of a list:

stack = [ root.keys() ]     # Result: [ [root keys] ]

Going in reverse order from last to first, lookup each key in the dictionary to see if its value is (also) a dictionary. If not, print the key then delete it. However if the value for the key is a dictionary, print the key then append the keys for that value to the end of the stack, and start processing that list in the same way, repeating recursively for each new list of keys.

If the value for the second key in each list were a dictionary you would have something like this after several rounds:

[['key 1','key 2'],['key 2.1','key 2.2'],['key 2.2.1','key 2.2.2'],[`etc.`]]

The upside to this approach is that the indent is just \t times the length of the stack:

indent = "\t" * len(stack)

The downside is that in order to check each key you need to hash through to the relevant sub-dictionary, though this can be handled easily with a list comprehension and a simple for loop:

path = [li[-1] for li in stack]
# The last key of every list of keys in the stack

sub = root
for p in path:
    sub = sub[p]


if type(sub) == dict:
    stack.append(sub.keys()) # And so on

Be aware that this approach will require you to cleanup trailing empty lists, and to delete the last key in any list followed by an empty list (which of course may create another empty list, and so on).

There are other ways to implement this approach but hopefully this gives you a basic idea of how to do it.

EDIT: If you don't want to go through all that, the pprint module prints nested dictionaries in a nice format.

danwroy
  • 47
  • 6
0

Here's something that will print any sort of nested dictionary, while keeping track of the "parent" dictionaries along the way.

dicList = list()

def prettierPrint(dic, dicList):
count = 0
for key, value in dic.iteritems():
    count+=1
    if str(value) == 'OrderedDict()':
        value = None
    if not isinstance(value, dict):
        print str(key) + ": " + str(value)
        print str(key) + ' was found in the following path:',
        print dicList
        print '\n'
    elif isinstance(value, dict):
        dicList.append(key)
        prettierPrint(value, dicList)
    if dicList:
         if count == len(dic):
             dicList.pop()
             count = 0

prettierPrint(dicExample, dicList)

This is a good starting point for printing according to different formats, like the one specified in OP. All you really need to do is operations around the Print blocks. Note that it looks to see if the value is 'OrderedDict()'. Depending on whether you're using something from Container datatypes Collections, you should make these sort of fail-safes so the elif block doesn't see it as an additional dictionary due to its name. As of now, an example dictionary like

example_dict = {'key1': 'value1',
            'key2': 'value2',
            'key3': {'key3a': 'value3a'},
            'key4': {'key4a': {'key4aa': 'value4aa',
                               'key4ab': 'value4ab',
                               'key4ac': 'value4ac'},
                     'key4b': 'value4b'}

will print

key3a: value3a
key3a was found in the following path: ['key3']

key2: value2
key2 was found in the following path: []

key1: value1
key1 was found in the following path: []

key4ab: value4ab
key4ab was found in the following path: ['key4', 'key4a']

key4ac: value4ac
key4ac was found in the following path: ['key4', 'key4a']

key4aa: value4aa
key4aa was found in the following path: ['key4', 'key4a']

key4b: value4b
key4b was found in the following path: ['key4']

~altering code to fit the question's format~

lastDict = list()
dicList = list()
def prettierPrint(dic, dicList):
    global lastDict
    count = 0
    for key, value in dic.iteritems():
        count+=1
        if str(value) == 'OrderedDict()':
            value = None
        if not isinstance(value, dict):
            if lastDict == dicList:
                sameParents = True
            else:
                sameParents = False

            if dicList and sameParents is not True:
                spacing = ' ' * len(str(dicList))
                print dicList
                print spacing,
                print str(value)

            if dicList and sameParents is True:
                print spacing,
                print str(value)
            lastDict = list(dicList)

        elif isinstance(value, dict):
            dicList.append(key)
            prettierPrint(value, dicList)

        if dicList:
             if count == len(dic):
                 dicList.pop()
                 count = 0

Using the same example code, it will print the following:

['key3']
         value3a
['key4', 'key4a']
                  value4ab
                  value4ac
                  value4aa
['key4']
         value4b

This isn't exactly what is requested in OP. The difference is that a parent^n is still printed, instead of being absent and replaced with white-space. To get to OP's format, you'll need to do something like the following: iteratively compare dicList with the lastDict. You can do this by making a new dictionary and copying dicList's content to it, checking if i in the copied dictionary is the same as i in lastDict, and -- if it is -- writing whitespace to that i position using the string multiplier function.

gavin
  • 41
  • 1
  • 1
  • 3
0

Use this function:

def pretty_dict(d, n=1):
    for k in d:
        print(" "*n + k)
        try:
            pretty_dict(d[k], n=n+4)
        except TypeError:
            continue

Call it like this:

pretty_dict(mydict)
fiftytwocards
  • 117
  • 1
  • 5
  • 1
    This doesn't work if the values are strings. It prints each character of the string on a new line, but the keys seem to work okay. – Anthony Feb 09 '20 at 17:52
0

This is what I came up with while working on a class that needed to write a dictionary in a .txt file:

@staticmethod
def _pretty_write_dict(dictionary):

    def _nested(obj, level=1):
        indentation_values = "\t" * level
        indentation_braces = "\t" * (level - 1)
        if isinstance(obj, dict):
            return "{\n%(body)s%(indent_braces)s}" % {
                "body": "".join("%(indent_values)s\'%(key)s\': %(value)s,\n" % {
                    "key": str(key),
                    "value": _nested(value, level + 1),
                    "indent_values": indentation_values
                } for key, value in obj.items()),
                "indent_braces": indentation_braces
            }
        if isinstance(obj, list):
            return "[\n%(body)s\n%(indent_braces)s]" % {
                "body": "".join("%(indent_values)s%(value)s,\n" % {
                    "value": _nested(value, level + 1),
                    "indent_values": indentation_values
                } for value in obj),
                "indent_braces": indentation_braces
            }
        else:
            return "\'%(value)s\'" % {"value": str(obj)}

    dict_text = _nested(dictionary)
    return dict_text

Now, if we have a dictionary like this:

some_dict = {'default': {'ENGINE': [1, 2, 3, {'some_key': {'some_other_key': 'some_value'}}], 'NAME': 'some_db_name', 'PORT': '', 'HOST': 'localhost', 'USER': 'some_user_name', 'PASSWORD': 'some_password', 'OPTIONS': {'init_command': 'SET foreign_key_checks = 0;'}}}

And we do:

print(_pretty_write_dict(some_dict))

We get:

{
    'default': {
        'ENGINE': [
            '1',
            '2',
            '3',
            {
                'some_key': {
                    'some_other_key': 'some_value',
                },
            },
        ],
        'NAME': 'some_db_name',
        'OPTIONS': {
            'init_command': 'SET foreign_key_checks = 0;',
        },
        'HOST': 'localhost',
        'USER': 'some_user_name',
        'PASSWORD': 'some_password',
        'PORT': '',
    },
}
  • you can simplify the idea to matching object types against another dictionaries containing the type + according string. – Jay-Pi Oct 05 '22 at 10:39
0

Another possibility is to use the "PrettyPrint" function of the PythonExtensionsCollection, that can be found here:

https://pypi.org/project/PythonExtensionsCollection/

"PrettyPrint" is described in: https://github.com/test-fullautomation/python-extensions-collection/blob/develop/PythonExtensionsCollection/PythonExtensionsCollection.pdf

HolQue
  • 1
  • 2
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/34617110) – TheTridentGuy supports Ukraine Jul 03 '23 at 16:07