我正在尝试使用 Pythons Rich 打印
dict()
。根据我的理解,这应该在不同的行等上输出数据。有点像pprint
。
但我得到:
>>> from rich import print
>>> print(output)
{'GigabitEthernet0/1': {'description': '## Connected to leaf-2 ##', 'type': 'iGbE', 'oper_status': 'up',
'phys_address': '5000.0009.0001', 'port_speed': 'auto speed', 'mtu': 1500, 'enabled': True, 'bandwidth': 1000000,
'flow_control': {'receive': False, 'send': False}, 'mac_address': '5000.0009.0001', 'auto_negotiate': True,
'port_channel': {'port_channel_member': False}, 'duplex_mode': 'auto', 'delay': 10, 'accounting': {'other': {'pkts_in':
0, 'chars_in': 0, 'pkts_out': 431258, 'chars_out': 25875480}, 'ip': {'pkts_in': 513383, 'chars_in': 42910746,
'pkts_out': 471188, 'chars_out': 45342027}, 'dec mop': {'pkts_in': 0, 'chars_in': 0, 'pkts_out': 7163, 'chars_out':
551551}, 'arp': {'pkts_in': 3845, 'chars_in': 230700, 'pkts_out': 3846, 'chars_out': 230760}, 'cdp': {'pkts_in': 72010,
'chars_in': 18866620, 'pkts_out': 79879, 'chars_out': 31221768}}, 'ipv4': {'10.1.1.5/30': {'ip': '10.1.1.5', ...
有什么建议吗?
TL;DR 如果您的字典结果不是 dict,请进行显式转换。
从你的字典的内容我假设你的
output
来自Cisco IOS等网络设备配置,我对这些领域一无所知,无法弄清楚你从哪里获取数据。
您用来获取
output
的模块或脚本可能实际上返回了一个名为 MappingProxyType的
dict
外观类型。
我推测这就是为什么你的文本是彩色的但没有美化的原因。
例如,让我们看看
rich.print
与 str.__dict__
做了什么:
>>> from rich import print
>>> print(str.__dict__)
这看起来像这样,就像你的一样。
请注意,这是在 WSL2 中运行的 xfce4 终端,被吸引到 X410 X-server。功能齐全的终端。
这确实看起来像 plain
dict
,但让我们检查一下它实际上是什么:
>>> type(str.__dict__)
<class 'mappingproxy'>
>>> from types import MappingProxyType
>>> isinstance(str.__dict__, MappingProxyType)
True
>>> isinstance(str.__dict__, dict)
False
如您所见,尽管它的输出看起来像一本字典,但事实并非如此。
types.MappingProxyType
本质上是一个只读字典,不一定是dict
。像 rich
这样的第三方库的开发者可能已经忘记了这种类型的存在。如果是这种情况,那么 rich.print
将执行内置 print()
的操作:调用 __repr__
/__str__
- 现在只需将其视为字符串即可。
我们可以通过传递看起来像方法的 __repr__
的
string来确认此行为,并且仍然得到富文本处理。
也可以自己创建
MappingProxyType
的实例。
>>> from types import MappingProxyType
>>> from rich import print
>>> data = {f"{n}": n for n in range(11)}
>>> print(data)
{
'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 7,
'8': 8,
'9': 9,
'10': 10
}
>>> print(MappingProxyType(data))
{'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
'10': 10}
从中您可以看到类型如何影响
rich.print
的输出。
要修复,只需将
types.MappingProxyType
转换为 dict
。
>>> from rich import print
>>> print(dict(str.__dict__))
这比以前更漂亮了 - 不包括
__doc__
值,它是单个字符串并且无济于事。
@jupiterbjy 的答案是正确的,但我想通过提供一个不需要手动在每个
dict
上转换为 repr()
的解决方案来扩展它。
如果您希望自定义对象像字典代码库范围内的那样进行再现,您可以添加一个
__rich_repr__
方法。
from types import MappingProxyType
class CustomDictType(MappingProxyType):
...
def __rich_repr__(self):
return (dict(self),)
有关更多信息,请参阅文档:https://rich.readthedocs.io/en/stable/pretty.html#rich-repr-protocol
benedict
对象执行此操作,您可以像这样对基类进行猴子修补:
import benedict
benedict.benedict.__rich_repr__ = lambda self: (dict(self),)
(这应该小心完成,因为猴子补丁会使代码库更难维护/调试)