Kurt Peek Kurt Peek - 1 month ago 20
Python Question

How to pretty print dictionaries in iPython

I'm currently using RethinkDB, which has a nice web UI with a Data Explorer which allows the user to print out the contents of the database like this:

enter image description here

Note that each key-value pair starts on a new line, and the keys and values (mostly) have different colors. By contrast, if I print out the same using iPython, I get an almost illegible result:

enter image description here

This is slightly ameliorated if I iterate over the cursor and

print
each item, like so:

enter image description here

However, this requires more typing and still doesn't look as good as the RethinkDB web UI. Is there perhaps an iPython plugin that I can install to improve the appearance of the printed output?

(I had a look at pprint, but this seems to control only the positioning of the text and not its color).

Answer

You could use json.dumps():

import json 

for row in r.db(....).run(conn):
    print(json.dumps(row, indent=4))

Although this does not display the keys in sorted order, as appears to be the case in the example, it might be sufficient for your needs. As pointed out by @coder, you json.dumps() can sort the keys by specifying the sort_keys=True parameter.

for row in r.db(....).run(conn):
    print(json.dumps(row, indent=4, sort_keys=True))

It might also be possible to print the object directly (haven't tested this):

print(json.dumps(r.db(....).run(conn), indent=4, sort_keys=True)

which might also print out the surrounding "list" object.


To handle objects that do not support serialisation to JSON you can use a custom JSONEncoder. Here is an example which handles datetime.datetime objects:

from datetime import datetime

class DateTimeAwareJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            tz = obj.tzname()
            return obj.ctime() + (' {}'.format(tz) if tz else '')
        return super(DateTimeAwareJSONEncoder, self).default(obj)

for row in r.db(....).run(conn):
    print(json.dumps(row, indent=4, sort_keys=True, cls=DateTimeAwareJSONEncoder))

You can use datetime.strftime() to format the date time string as required.