简体   繁体   English

在 pprint output 中禁用排序机制

[英]Disabling sorting mechanism in pprint output

I have big dictionary which I`m printing for viewing with prettyprint, but how I can keep formatting but kill sorting mechanism in pprint?我有一个很大的字典,我正在打印它以使用 prettyprint 查看,但是我如何才能保持格式但在 pprint 中取消排序机制?

Python 3.8 or newer: Python 3.8 或更新版本:

Use sort_dicts=False :使用sort_dicts=False

pprint.pprint(data, sort_dicts=False)

Python 3.7 or older: Python 3.7 或更早版本:

You can monkey patch the pprint module.您可以猴子修补pprint 模块。

import pprint

pprint.pprint({"def":2,"ghi":3,"abc":1,})
pprint._sorted = lambda x:x
# Or, for Python 3.7:
# pprint.sorted = lambda x, key=None: x
pprint.pprint({"def":2,"ghi":3, "abc":1})

Since the 2nd output is essentiallly randomly sorted, your output may be different from mine:由于第二个输出基本上是随机排序的,因此您的输出可能与我的不同:

{'abc': 1, 'def': 2, 'ghi': 3}
{'abc': 1, 'ghi': 3, 'def': 2}

Another version that is more complex, but easier to use: 另一个更复杂但更易于使用的版本:
 import pprint import contextlib @contextlib.contextmanager def pprint_nosort(): # Note: the pprint implementation changed somewhere # between 2.7.12 and 3.7.0. This is the danger of # monkeypatching! try: # Old pprint orig,pprint._sorted = pprint._sorted, lambda x:x except AttributeError: # New pprint import builtins orig,pprint.sorted = None, lambda x, key=None:x try: yield finally: if orig: pprint._sorted = orig else: del pprint.sorted # For times when you don't want sorted output with pprint_nosort(): pprint.pprint({"def":2,"ghi":3, "abc":1}) # For times when you do want sorted output pprint.pprint({"def":2,"ghi":3, "abc":1})

As of Python 3.8, you can finally disable this using sort_dicts=False .从 Python 3.8 开始,您最终可以使用sort_dicts=False禁用它 Note that dictionaries are insertion-ordered since Python 3.7 (and in practice, even since 3.6).请注意,字典从 Python 3.7 开始是插入排序的(实际上,甚至从 3.6 开始)。

import pprint

data = {'not': 'sorted', 'awesome': 'dict', 'z': 3, 'y': 2, 'x': 1}
pprint.pprint(data, sort_dicts=False)
# prints {'not': 'sorted', 'awesome': 'dict', 'z': 3, 'y': 2, 'x': 1}

Alternatively, create a pretty printer object :或者,创建一个漂亮的打印机对象

pp = pprint.PrettyPrinter(sort_dicts=False)
pp.pprint(data)

This does not affect sets (which are still sorted), but then sets do not have insertion-ordering guarantees.这不会影响集合(仍然是排序的),但是集合没有插入顺序保证。

Instead of pprint.pprint , save yourself 4 characters and use pprint.pp , which doesn't sort:而不是pprint.pprint ,为自己节省 4 个字符并使用pprint.pp ,它不会排序:

pprint.pp(object, *args, sort_dicts=False, **kwargs)

Prints the formatted representation of object followed by a newline.打印对象的格式化表示,后跟换行符。 If sort_dicts is false (the default), dictionaries will be displayed with their keys in insertion order, otherwise the dict keys will be sorted.如果sort_dicts为 false(默认值),字典将按插入顺序显示其键,否则将排序字典键。 args and kwargs will be passed to pprint() as formatting parameters. argskwargs将作为格式化参数传递给pprint()

New in version 3.8. 3.8 版中的新功能。

You can subclass PrettyPrinter and remove the sorted(object.items()) from _pprint_dict .您可以继承PrettyPrinter并从_pprint_dict中删除sorted(object.items())

NOTE: this code is Python 3.5+注意:此代码是 Python 3.5+

# unsorted_pprint.py

from pprint import PrettyPrinter, _builtin_scalars, _recursion

__all__ = [
    'UnsortedPrettyPrinter',
    'pprint2',
    'pformat2',
]


class UnsortedPrettyPrinter(PrettyPrinter):
    """Pretty printer that retains original dict ordering
    """
    def __init__(self, *args, **kwargs):
        super().__init__()

        self._dispatch = {
            **self._dispatch,
            dict.__repr__: self._pprint_dict,
        }

    @staticmethod
    def _pprint_dict(self, object, stream, indent, allowance, context, level):
        write = stream.write
        write('{')
        if self._indent_per_level > 1:
            write((self._indent_per_level - 1) * ' ')
        length = len(object)
        if length:
            items = object.items()
            self._format_dict_items(items, stream, indent, allowance + 1,
                                    context, level)
        write('}')

    def format(self, object, context, maxlevels, level):
        """Format object for a specific context, returning a string
        and flags indicating whether the representation is 'readable'
        and whether the object represents a recursive construct.
        """
        return self._safe_repr(object, context, maxlevels, level)

    def _safe_repr(self, object, context, maxlevels, level):
        typ = type(object)
        if typ in _builtin_scalars:
            return repr(object), True, False

        r = getattr(typ, "__repr__", None)
        if issubclass(typ, dict) and r is dict.__repr__:
            if not object:
                return "{}", True, False
            objid = id(object)
            if maxlevels and level >= maxlevels:
                return "{...}", False, objid in context
            if objid in context:
                return _recursion(object), False, True
            context[objid] = 1
            readable = True
            recursive = False
            components = []
            append = components.append
            level += 1
            saferepr = self._safe_repr
            items = object.items()
            for k, v in items:
                krepr, kreadable, krecur = saferepr(k, context, maxlevels, level)
                vrepr, vreadable, vrecur = saferepr(v, context, maxlevels, level)
                append("%s: %s" % (krepr, vrepr))
                readable = readable and kreadable and vreadable
                if krecur or vrecur:
                    recursive = True
            del context[objid]
            return "{%s}" % ", ".join(components), readable, recursive

        if (issubclass(typ, list) and r is list.__repr__) or \
            (issubclass(typ, tuple) and r is tuple.__repr__):
            if issubclass(typ, list):
                if not object:
                    return "[]", True, False
                format = "[%s]"
            elif len(object) == 1:
                format = "(%s,)"
            else:
                if not object:
                    return "()", True, False
                format = "(%s)"
            objid = id(object)
            if maxlevels and level >= maxlevels:
                return format % "...", False, objid in context
            if objid in context:
                return _recursion(object), False, True
            context[objid] = 1
            readable = True
            recursive = False
            components = []
            append = components.append
            level += 1
            for o in object:
                orepr, oreadable, orecur = self._safe_repr(o, context, maxlevels, level)
                append(orepr)
                if not oreadable:
                    readable = False
                if orecur:
                    recursive = True
            del context[objid]
            return format % ", ".join(components), readable, recursive

        rep = repr(object)
        return rep, (rep and not rep.startswith('<')), False


def pprint2(object, stream=None, indent=1, width=80, depth=None, *,
           compact=False):
    """Pretty-print a Python object to a stream [default is sys.stdout].

    dict items are left unsorted.
    """
    printer = UnsortedPrettyPrinter(
        stream=stream,
        indent=indent,
        width=width,
        depth=depth,
        compact=compact,
    )
    printer.pprint(object)


def pformat2(object, indent=1, width=80, depth=None, *, compact=False):
    """Format a Python object into a pretty-printed representation.

    dict items are left unsorted.
    """
    return UnsortedPrettyPrinter(
        indent=indent,
        width=width,
        depth=depth,
        compact=compact,
    ).pformat(object)

I know that I am a bit late here but my preferred way to disable sorting dicts is by using partial :我知道我在这里有点晚了,但我更喜欢禁用排序字典的方法是使用partial

from functools import partial
from pprint import pprint

pprint = partial(pprint, sort_dicts=False)

Personally I like this way as it introduces the smallest diffs.我个人喜欢这种方式,因为它引入了最小的差异。

It has the benefit of monkey patching in that you only have to make changes at one spot(unlike other options) without having to mess with the internals of pprint .它具有猴子修补的好处,因为您只需在一个地方进行更改(与其他选项不同),而不必弄乱pprint的内部结构。

I'm using py3.8 but this should work from whenever sort_dicts option was added.我正在使用 py3.8 但这应该在添加sort_dicts选项时起作用。

You can use json.dumps with indent=4 .您可以将json.dumpsindent=4一起使用。 This creates a formatted string, that can be printed nicely and does not sort keys by default.这将创建一个格式化的字符串,可以很好地打印并且默认情况下不会对键进行排序。

Note: this works also for old pythons注意:这也适用于旧蟒蛇

import json
d = {3:4, 1:2, 5:6}
print(json.dumps(d, indent=4))

output: output:

{
    "3": 4,
    "1": 2,
    "5": 6
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM