Complex sorting of nested data I am retrieving data from Postgres (jsonb type) and I need to return an OrderedDict that has a predictable order for human and machine consumption.  There are some common(ish) keys that should be used to direct precedence of values of common types (based on a predefined order and if sort_order is defined).  Otherwise, sort order should fall back to key based lexicographic ordering.

The general intent is to have a predictable, 'sane', represenation of composite dicts.

The basic algorithm is: 


Dicts come before lists 
Values that are NOT iterables or mapping take precedence over objects that are.  
Values of the same type whose keys are not in sort_order are considered equal and should be sorted lexicographically.  
Obj A takes precedence over Obj B if type(A[0]) == type(B)  and [0] in sort_order not B[0] in sort_order
if all([type(A[1]) == type(B[1]), A[0] in sort_order, B[0] in sort_order]) then the index position of the object key is the precedence determinant.  


I have attempted several implementations, but I have not been able to come up with anything that I would consider pythonic/elegant.

Here is the latest incarnation:

# -*- coding: utf-8 -*-

import json
from collections import OrderedDict


def dict_sort(obj, sort_order=None):
    def seq(s, o=None, v=None):
        return str(s) + str(o) + str(v) if o is not None else str(s)

    order_seq = None
    if sort_order is not None and obj[0] in sort_order:
        order_seq = [i for i, v in enumerate(sort_order) if v == obj[0]][0]

    if isinstance(obj[1], dict):
        return seq(2, order_seq, obj[0]) if order_seq else seq(3)
    elif isinstance(obj[1], list):
        return seq(4, order_seq, obj[0]) if order_seq else seq(5)
    else:
        return seq(0, order_seq, obj[0]) if order_seq else seq(1)


def comp_sort(obj, sort_order=None):
    data = OrderedDict()
    if isinstance(obj, dict):
        for key, value in sorted(obj.items(), key=lambda d: dict_sort(d, sort_order)):
            if isinstance(value, dict) or isinstance(value, list):
                data[key] = comp_sort(value, sort_order)
            else:
                data[key] = value
    elif isinstance(obj, list):
        try:
            return sorted(obj)
        except:
            items = []
            for value in obj:
                if isinstance(value, dict) or isinstance(value, list):
                    items.append(comp_sort(value, sort_order))
                else:
                    items.append(value)
            return items
    return data

# thx herk


Here is a sample data set.
You can use a list comprehension to avoid verbosity:

        items = []
        for value in obj:
            if isinstance(value, dict) or isinstance(value, list):
                items.append(comp_sort(value, sort_order))
            else:
                items.append(value)
        return items


Becomes:

is_dict_or_list = isinstance(value, dict) or isinstance(value, list) 
return [comp_sort(value, sort_order) if is_dict_or_list else value
               for value in obj ]


Remember to specify:

except ExpectedError:


And not

except:


The latter will swallow anything and harden debugging.