我可以让 python3 中的 pprint 不拆分字符串,就像 python2 中那样吗?

Can I make pprint in python3 not split strings, like in python2?

有没有办法告诉 Python 3 中的 pprint 不要在空格处拆分字符串? Python 2 的 pprint 没有这样做。可以禁用此行为吗?我查看了 pprint 的源代码,但似乎没有我看到的选项。

我能以某种方式欺骗它吗?

这是我得到的示例:

>>> PP.pprint("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZ",width=-1,compact=True)
('ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ '
 'ZZZZZ')

这就是我想要的:

>>> PP.pprint("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZ",width=-1,compact=True)
('ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZ')

澄清一下,我确实希望它遵循宽度,而不是字符串。所以当我看到例如:

PP.pprint(["ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZ","CATS"])

我要:

['ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZ',
 'CATS']

不是:

['ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ '
 'ZZZZZZZZZZZZZ',
 'CATS']

您可以将 width 选项设置为一个非常大的值,例如 sys.maxsize:

>>> import sys
>>> import pprint as PP
>>> PP.pprint("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZ",width=sys.maxsize,compact=True)
'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZ'

设置width-1没有特殊意义。

唯一的其他选择是子class PrettyPrinter() class,并包装 _format() 方法:

import sys
from pprint import PrettyPrinter

class NoStringWrappingPrettyPrinter(PrettyPrinter):
    def _format(self, object, *args):
        if isinstance(object, str):
            width = self._width
            self._width = sys.maxsize
            try:
                super()._format(object, *args)
            finally:
                self._width = width
        else:
            super()._format(object, *args)

NoStringWrappingPrettyPrinter().pprint(yourobject)

这会将宽度设置为 sys.maxsize 仅适用于字符串:

>>> NoStringWrappingPrettyPrinter().pprint(["ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZ", "CATS"])
['ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZ',
 'CATS']

看来您需要将宽度设置为字符串的长度 + 3(对于两边的引号和换行符)绝对最小值。

>>> x = 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZ'
>>> PP.pprint(x, width=len(x))
'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ '
'ZZZZZ'
>>> PP.pprint(x, width=len(x) + 3)
'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ZZZZZ'

另一种方法,类似于 Martijn Pieters 的方法,但较少依赖 pprint 的内部结构,是继承 PrettyPrinter 并覆盖 format。 在内部你可以委托给 super().format 但在结果中你可以伪造字符串的长度,这样它们就不会被拆分。这依赖于不查看字符串长度的输出流(例如 sys.stdoutStringIO())。

class Python2PrettyPrinter(pprint.PrettyPrinter):
    class _fake_short_str(str):
        def __len__(self):
            return 1 if super().__len__() else 0

    def format(self, object, context, maxlevels, level):
        res = super().format(object, context, maxlevels, level)
        if isinstance(object, str):
            return (self._fake_short_str(res[0]), ) + res[1:]
        return res

    from io import StringIO
    assert StringIO().write(_fake_short_str('_' * 1000)) == 1000


Python2PrettyPrinter().pprint(["TEST " * 20] * 2)
# ['TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST ',
#  'TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST ']

100% 干净的方法是为所有支持的容器 类 修改 format 的行为,并将每个字符串替换为具有相同表示的自定义对象。

对于列表,您可以尝试json.dump。代码:

import json
from pprint import pprint
import sys

li = ['zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz zzz', 'cats']

print("pprint directly:")
pprint(li)
print('-' * 20)
print("pprint with large width:")
pprint(li, width=sys.maxsize, compact=True)
print('-' * 20)
print("json dumps:")
print(json.dumps(li, indent=4))

输出:

pprint directly:
['zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz '
 'zzz',
 'cats']
--------------------
pprint with large width:
['zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz zzz', 'cats']
--------------------
json dumps:
[
    "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz zzz",
    "cats"
]

设置较大的宽度使得pprint即使列表对象很长也不会换行