किसी भी तरह से बहुत सुंदर प्रिंट के लिए शब्दकोशों का आदेश दिया?


97

मुझे पायथन में पाइंट मॉड्यूल पसंद है। मैं परीक्षण और डिबगिंग के लिए इसका उपयोग करता हूं। मैं बार-बार चौड़ाई विकल्प का उपयोग यह सुनिश्चित करने के लिए करता हूं कि आउटपुट मेरे टर्मिनल विंडो में अच्छी तरह से फिट बैठता है।

यह तब तक ठीक काम करता है जब तक कि उन्होंने पायथन 2.7 में नया ऑर्डर किया गया शब्दकोश प्रकार नहीं जोड़ा (एक और अच्छा फीचर जो मुझे वास्तव में पसंद है)। अगर मैं एक ऑर्डर किए गए शब्दकोश को सुंदर प्रिंट करने की कोशिश करता हूं, तो यह अच्छी तरह से नहीं दिखता है। प्रत्येक की-वैल्यू जोड़ी को अपनी लाइन पर रखने के बजाय, पूरी चीज एक लंबी लाइन पर दिखाई देती है, जो कई बार लपेटती है और पढ़ने में कठिन होती है।

क्या किसी के पास पुराने अनगढ़ शब्दकोश की तरह इसे अच्छी तरह से छापने का एक तरीका है? मैं शायद कुछ पता लगा सकता हूं, संभवत: प्रिटीप्रिन्टर.फॉर्मैट विधि का उपयोग करके, अगर मैं पर्याप्त समय बिताता हूं, लेकिन मैं सोच रहा हूं कि क्या यहां कोई पहले से ही एक समाधान जानता है।

अद्यतन: मैंने इसके लिए एक बग रिपोर्ट दायर की है। आप इसे http://bugs.python.org/issue10592 पर देख सकते हैं ।


जवाबों:


133

अस्थायी वर्कअराउंड के रूप में आप JSON फॉर्मेट में डंपिंग की कोशिश कर सकते हैं। आप कुछ प्रकार की जानकारी खो देते हैं, लेकिन यह अच्छा लग रहा है और आदेश रखता है।

import json

pprint(data, indent=4)
# ^ugly

print(json.dumps(data, indent=4))
# ^nice

7
@scottmrogowski क्यों नहीं बस pprint.pprint(dict(data))?
अल्फ़

2
pprint.pprint(dict(data))यदि आप कुंजियों के क्रम की परवाह नहीं करते हैं तो अच्छी तरह से काम करता है। व्यक्तिगत रूप से, मैं चाहता हूँ __repr__के लिए OrderedDictइस तरह उत्पादन का उत्पादन लेकिन चाबियों का क्रम की रक्षा करेगा।
ws_e_c421 15

9
@Alfe अगर तानाशाह ने आदेश दिया है, तो वे अच्छी तरह से प्रदर्शित नहीं होंगे
Catskul

1
कुंजी के रूप में पूर्णांक पर भी विफल रहता है
DimmuR

2
@ शेल्फ: क्योंकि तब आउटपुट का आदेश नहीं दिया जाता है। पहली जगह में डिक्टेड के बजाय ऑर्डरेड डिक्ट का इस्तेमाल किया जाता है, ऐसा इसलिए है क्योंकि ऑर्डर मायने रखता है।
तेईकिन

15

यदि आपका आर्डर डिक्लेयर्ड एक अल्फा सॉर्ट है, तो प्रिंट से पहले एक तानाशाह सॉर्ट करेगा।

pprint(dict(o.items()))

2
चूंकि आर्डर किए गए आदेशों को आदेश आदेश द्वारा आदेशित किया जाता है, इसलिए यह संभवतः उपयोग के एक छोटे प्रतिशत पर लागू होता है। भले ही, आयुध डिपो dictको एक लाइन में रखने से सब कुछ के मुद्दे से बचना चाहिए।
9

8

यहां एक और जवाब है जो pprint()आंतरिक रूप से स्टॉक फ़ंक्शन को ओवरराइड करके और उपयोग करके काम करता है । मेरे पहले वाले के विपरीत यह किसी अन्य कंटेनर के अंदर जैसे हैंडल करेगा और दिए गए किसी भी वैकल्पिक कीवर्ड तर्क को भी संभालने में सक्षम होना चाहिए - हालांकि यह आउटपुट पर नियंत्रण का एक ही डिग्री नहीं है जो दूसरे ने वहन किया है।OrderedDictlist

यह स्टॉक फ़ंक्शन के आउटपुट को एक अस्थायी बफर में पुनर्निर्देशित करके संचालित करता है और फिर आउटपुट स्ट्रीम पर भेजने से पहले शब्द लपेटता है। जबकि उत्पादित अंतिम उत्पादन असाधारण रूप से सुंदर नहीं है, यह सभ्य है और वर्कअराउंड के रूप में उपयोग करने के लिए "काफी अच्छा" हो सकता है।

अद्यतन 2.0

मानक पुस्तकालय textwrapमॉड्यूल का उपयोग करके सरलीकृत , और पायथन 2 और 3 दोनों में काम करने के लिए संशोधित।

from collections import OrderedDict
try:
    from cStringIO import StringIO
except ImportError:  # Python 3
    from io import StringIO
from pprint import pprint as pp_pprint
import sys
import textwrap

def pprint(object, **kwrds):
    try:
        width = kwrds['width']
    except KeyError: # unlimited, use stock function
        pp_pprint(object, **kwrds)
        return
    buffer = StringIO()
    stream = kwrds.get('stream', sys.stdout)
    kwrds.update({'stream': buffer})
    pp_pprint(object, **kwrds)
    words = buffer.getvalue().split()
    buffer.close()

    # word wrap output onto multiple lines <= width characters
    try:
        print >> stream, textwrap.fill(' '.join(words), width=width)
    except TypeError:  # Python 3
        print(textwrap.fill(' '.join(words), width=width), file=stream)

d = dict((('john',1), ('paul',2), ('mary',3)))
od = OrderedDict((('john',1), ('paul',2), ('mary',3)))
lod = [OrderedDict((('john',1), ('paul',2), ('mary',3))),
       OrderedDict((('moe',1), ('curly',2), ('larry',3))),
       OrderedDict((('weapons',1), ('mass',2), ('destruction',3)))]

नमूना उत्पादन:

pprint(d, width=40)

»   {'john': 1, 'mary': 3, 'paul': 2}

pprint(od, width=40)

» OrderedDict([('john', 1), ('paul', 2),
   ('mary', 3)])

pprint(lod, width=40)

» [OrderedDict([('john', 1), ('paul', 2),
   ('mary', 3)]), OrderedDict([('moe', 1),
   ('curly', 2), ('larry', 3)]),
   OrderedDict([('weapons', 1), ('mass',
   2), ('destruction', 3)])]


मैंने कोशिश की और यह काम करता है। जैसा कि आपने कहा, यह सबसे सुंदर नहीं है, लेकिन यह अब तक का सबसे अच्छा समाधान है।
एलियास ज़मरिया

7

आदेशित आदेश को मुद्रित करने के लिए, उदाहरण के लिए

from collections import OrderedDict

d=OrderedDict([
    ('a', OrderedDict([
        ('a1',1),
        ('a2','sss')
    ])),
    ('b', OrderedDict([
        ('b1', OrderedDict([
            ('bb1',1),
            ('bb2',4.5)])),
        ('b2',4.5)
    ])),
])

मैं करता हूँ

def dict_or_OrdDict_to_formatted_str(OD, mode='dict', s="", indent=' '*4, level=0):
    def is_number(s):
        try:
            float(s)
            return True
        except ValueError:
            return False
    def fstr(s):
        return s if is_number(s) else '"%s"'%s
    if mode != 'dict':
        kv_tpl = '("%s", %s)'
        ST = 'OrderedDict([\n'; END = '])'
    else:
        kv_tpl = '"%s": %s'
        ST = '{\n'; END = '}'
    for i,k in enumerate(OD.keys()):
        if type(OD[k]) in [dict, OrderedDict]:
            level += 1
            s += (level-1)*indent+kv_tpl%(k,ST+dict_or_OrdDict_to_formatted_str(OD[k], mode=mode, indent=indent, level=level)+(level-1)*indent+END)
            level -= 1
        else:
            s += level*indent+kv_tpl%(k,fstr(OD[k]))
        if i!=len(OD)-1:
            s += ","
        s += "\n"
    return s

print dict_or_OrdDict_to_formatted_str(d)

कौन सी पैदावार

"a": {
    "a1": 1,
    "a2": "sss"
},
"b": {
    "b1": {
        "bb1": 1,
        "bb2": 4.5
    },
    "b2": 4.5
}

या

print dict_or_OrdDict_to_formatted_str(d, mode='OD')

कौन सी पैदावार

("a", OrderedDict([
    ("a1", 1),
    ("a2", "sss")
])),
("b", OrderedDict([
    ("b1", OrderedDict([
        ("bb1", 1),
        ("bb2", 4.5)
    ])),
    ("b2", 4.5)
]))

5

यहां एक तरीका है जो कार्यान्वयन को हैक करता है pprintpprintमुद्रण से पहले कुंजियों को क्रमबद्ध करें, ताकि ऑर्डर को संरक्षित करने के लिए, हमें बस चाबी को उसी तरह बनाना होगा जिस तरह से हम चाहते हैं।

ध्यान दें कि यह items()फ़ंक्शन को प्रभावित करता है। तो आप पदचिह्न करने के बाद ओवरराइड किए गए कार्यों को संरक्षित और पुनर्स्थापित करना चाह सकते हैं।

from collections import OrderedDict
import pprint

class ItemKey(object):
  def __init__(self, name, position):
    self.name = name
    self.position = position
  def __cmp__(self, b):
    assert isinstance(b, ItemKey)
    return cmp(self.position, b.position)
  def __repr__(self):
    return repr(self.name)

OrderedDict.items = lambda self: [
    (ItemKey(name, i), value)
    for i, (name, value) in enumerate(self.iteritems())]
OrderedDict.__repr__ = dict.__repr__

a = OrderedDict()
a[4] = '4'
a[1] = '1'
a[2] = '2'
print pprint.pformat(a) # {4: '4', 1: '1', 2: '2'}

2
अच्छा है, लेकिन फिर उप-प्रकार कार्यों को ओवरराइड करना बेहतर है।
xmedeko

3

यहाँ एक ऑर्डरडीक को सुंदर प्रिंट करने के लिए मेरा दृष्टिकोण है

from collections import OrderedDict
import json
d = OrderedDict()
d['duck'] = 'alive'
d['parrot'] = 'dead'
d['penguin'] = 'exploded'
d['Falcon'] = 'discharged'
print(d)
print(json.dumps(d,indent=4))

OutPut:

OrderedDict([('duck', 'alive'), ('parrot', 'dead'), ('penguin', 'exploded'), ('Falcon', 'discharged')])

{
    "duck": "alive",
    "parrot": "dead",
    "penguin": "exploded",
    "Falcon": "discharged"
}

यदि आप क्रमबद्ध क्रम में कुंजियों के साथ सुंदर प्रिंट शब्दकोश चाहते हैं

print(json.dumps(indent=4,sort_keys=True))
{
    "Falcon": "discharged",
    "duck": "alive",
    "parrot": "dead",
    "penguin": "exploded"
}

@AlxVallejo आप उपयोग कर सकते हैं python3। कृपया जांच करें
CHINTAN VADGAMA

2

यह बहुत कच्चा है, लेकिन मुझे किसी भी मनमाने मैपिंग और Iterables से बनी डेटा संरचना की कल्पना करने के लिए एक तरीके की आवश्यकता थी और यह मैं हार मानने से पहले आया था। यह पुनरावर्ती है, इसलिए यह नेस्टेड संरचनाओं और सूचियों के माध्यम से ठीक हो जाएगा। मैंने कुछ भी संभालने के लिए संग्रह से मैपिंग और Iterable सार बेस कक्षाओं का उपयोग किया।

मैं लगभग अजगर कोड के साथ उत्पादन की तरह yaml के लिए लक्ष्य कर रहा था, लेकिन यह काफी नहीं बना।

def format_structure(d, level=0):
    x = ""
    if isinstance(d, Mapping):
        lenk = max(map(lambda x: len(str(x)), d.keys()))
        for k, v in d.items():
            key_text = "\n" + " "*level + " "*(lenk - len(str(k))) + str(k)
            x += key_text + ": " + format_structure(v, level=level+lenk)
    elif isinstance(d, Iterable) and not isinstance(d, basestring):
        for e in d:
            x += "\n" + " "*level + "- " + format_structure(e, level=level+4)
    else:
        x = str(d)
    return x

और कुछ टेस्ट डेटा ऑर्डरड डिक्ट का उपयोग करके और ऑर्डरेडडिक्ट्स की सूची ... (शीश पायथन को ऑर्डरडीडक्ट शाब्दिक रूप से बुरी तरह से सोखने की जरूरत है ...)

d = OrderedDict([("main",
                  OrderedDict([("window",
                                OrderedDict([("size", [500, 500]),
                                             ("position", [100, 900])])),
                               ("splash_enabled", True),
                               ("theme", "Dark")])),
                 ("updates",
                  OrderedDict([("automatic", True),
                               ("servers",
                                [OrderedDict([("url", "http://server1.com"),
                                              ("name", "Stable")]),
                                 OrderedDict([("url", "http://server2.com"),
                                              ("name", "Beta")]),
                                 OrderedDict([("url", "http://server3.com"),
                                              ("name", "Dev")])]),
                               ("prompt_restart", True)])),
                 ("logging",
                  OrderedDict([("enabled", True),
                               ("rotate", True)]))])

print format_structure(d)

निम्नलिखित उत्पादन प्राप्त करता है:

   main: 
               window: 
                         size: 
                             - 500
                             - 500
                     position: 
                             - 100
                             - 900
       splash_enabled: True
                theme: Dark
updates: 
            automatic: True
              servers: 
                     - 
                          url: http://server1.com
                         name: Stable
                     - 
                          url: http://server2.com
                         name: Beta
                     - 
                          url: http://server3.com
                         name: Dev
       prompt_restart: True
logging: 
       enabled: True
        rotate: True

मेरे पास बेहतर संरेखण के लिए str.format () का उपयोग करने के तरीके के साथ कुछ विचार थे, लेकिन इसमें खुदाई करने का मन नहीं था। आपको अपने इच्छित संरेखण के प्रकार के आधार पर फ़ील्ड की चौड़ाई को गतिशील रूप से निर्दिष्ट करना होगा, जो या तो मुश्किल या बोझिल हो जाएगा।

वैसे भी, यह मुझे पठनीय पदानुक्रमित फैशन में अपना डेटा दिखाता है, इसलिए यह मेरे लिए काम करता है!


2
def pprint_od(od):
    print "{"
    for key in od:
        print "%s:%s,\n" % (key, od[key]) # Fixed syntax
    print "}"

वहां आप ^ ^ जाएं

for item in li:
    pprint_od(item)

या

(pprint_od(item) for item in li)

मैं किसी ऐसे फंक्शन की तलाश कर रहा हूं, जिसमें ऑर्डरडीकिट्स के साथ-साथ अन्य प्रकारों को भी प्रिंट किया जा सके। मैं यह नहीं देखता कि मैं आपके फ़ंक्शन को सुंदर-प्रिंट करने के लिए कैसे कहूंगा, ऑर्डरडेडिकट्स की एक सूची।
एलियास ज़मरिया

-1 pprint_od()समारोह नहीं है काम - for key, item in odएक में बयान परिणाम ValueError: too many values to unpack और केवल उत्पादन इंडेंट अंतिम है " }" औरkey, item में printकोष्ठक में होना करने के लिए बयान की जरूरत है। वहाँ आप ^ ^
मार्टीन्यू

2

मैंने python3.5 पर इस अपवित्र बंदर-पैच आधारित हैक का परीक्षण किया है और यह काम करता है:

pprint.PrettyPrinter._dispatch[pprint._collections.OrderedDict.__repr__] = pprint.PrettyPrinter._pprint_dict


def unsorted_pprint(data):
    def fake_sort(*args, **kwargs):
        return args[0]
    orig_sorted = __builtins__.sorted
    try:
        __builtins__.sorted = fake_sort
        pprint.pprint(data)
    finally:
        __builtins__.sorted = orig_sorted

आप pprintसामान्य रूप से तानाशाही आधारित सारांश का उपयोग करते हैं और कॉल की अवधि के लिए छँटाई को भी अक्षम करते हैं ताकि मुद्रण के लिए वास्तव में कोई कुंजी न छांटे।


आप केवल pretty_print.pyएक स्थानीय मॉड्यूल के रूप में भी कॉपी कर सकते हैं और उस पर हैक कर सकते हैं ( sortedकॉल या जो आप चाहते हैं उसे हटा दें )।
कार्ल रोजेन

2

पायथन 3.8 के रूप में: कीवर्ड पैरामीटर pprint.PrettyPrinterको उजागर करता है sort_dicts

डिफ़ॉल्ट रूप से सही , इसे फाल्स पर सेट करने से डिक्शनरी अनसोल्ड हो जाएगी।

>>> from pprint import PrettyPrinter

>>> x = {'John': 1,
>>>      'Mary': 2,
>>>      'Paul': 3,
>>>      'Lisa': 4,
>>>      }

>>> PrettyPrinter(sort_dicts=False).pprint(x)

उत्पादन होगा:

{'John': 1, 
 'Mary': 2, 
 'Paul': 3,
 'Lisa': 4}

संदर्भ: https://docs.python.org/3/library/pprint.html


1

pprint()विधि केवल लागू है __repr__()उस में चीजों की विधि, औरOrderedDict यह की विधि में ज्यादा कुछ करने के लिए प्रकट नहीं होता है (या एक या कुछ नहीं है)।

यहाँ एक सस्ता उपाय है जो आपको काम करना चाहिए यदि आप PPRINT OUTPUT में दिखाई देने वाले आदेश के बारे में ध्यान न दें , जो कि एक बड़ा हो सकता है:

class PrintableOrderedDict(OrderedDict):
    def __repr__(self):
        return dict.__repr__(self)

मैं वास्तव में हैरान हूं कि ऑर्डर संरक्षित नहीं है ... आह ठीक है।


हैशमैप का उपयोग करके एक अजगर शब्दकोष लागू किया जाता है। इसलिए, एक बार जब आप एक ऑर्डर (ऑर्डर को संरक्षित करने के लिए एक बुनियादी तानाशाही और एक सूची का संयोजन) में परिवर्तित करते हैं, तो आप अपने ऑर्डर की जानकारी खो देते हैं। इसके अलावा, रीप विधि एक स्ट्रिंग को वापस करने वाली है जो कि अजगर कोड में ऑब्जेक्ट का प्रतिनिधित्व करेगी। दूसरे शब्दों में, obj == eval (repr (obj)), या, न्यूनतम repr (obj) == repr (eval (rej (obj))) पर। आर्डर किया गया डिक्लेयरडिप का रिप्रजेंट यह ठीक है। तानाशाही .__ repr__ आपको बहुत मानवीय पठनीय प्रतिनिधित्व देना पूरी तरह से तानाशाह ('{' और '}', आदि) का एक साइड इफेक्ट है। ऑर्डरडीड में यह नहीं है।
marr75

1

आप kzh उत्तर के इस सरलीकरण का भी उपयोग कर सकते हैं :

pprint(data.items(), indent=4)

यह आदेश को संरक्षित करता है और वेबवार्स्ट उत्तर ( जौन डंप के माध्यम से प्रिंट ) की तुलना में लगभग समान होगा ।


1

अजगर के लिए <3.8 (उदाहरण के लिए 3.6):

बंदर पैच pprint's sortedताकि इसे छँटाई से रोका जा सके। यह सब कुछ के रूप में अच्छी तरह से काम कर के लाभ होगा, और jsonजो कोई भी उपयोग करने की आवश्यकता के लिए विकल्प की तुलना में अधिक उपयुक्त है जैसे कि widthपैरामीटर:

import pprint
pprint.sorted = lambda arg, *a, **kw: arg

>>> pprint.pprint({'z': 1, 'a': 2, 'c': {'z': 0, 'a': 1}}, width=20)
{'z': 1,
 'a': 2,
 'c': {'z': 0,
       'a': 1}}

संपादित करें: सफाई

इस गंदे व्यवसाय को चलाने के बाद सफाई के लिए: pprint.sorted = sorted

वास्तव में साफ समाधान के लिए भी एक संदर्भ का उपयोग कर सकते हैं:

import pprint
import contextlib

@contextlib.contextmanager
def pprint_ordered():
    pprint.sorted = lambda arg, *args, **kwargs: arg
    yield
    pprint.sorted = sorted

# usage:

with pprint_ordered():
    pprint.pprint({'z': 1, 'a': 2, 'c': {'z': 0, 'a': 1}}, width=20)

# without it    
pprint.pprint({'z': 1, 'a': 2, 'c': {'z': 0, 'a': 1}}, width=20)

# prints: 
#    
# {'z': 1,
#  'a': 2,
#  'c': {'z': 0,
#        'a': 1}}
#
# {'a': 2,
#  'c': {'a': 1,
#        'z': 0},
#  'z': 1}

0

आप पुनर्परिभाषित कर सकते हैं pprint()और कॉल को रोक सकते हैं OrderedDict। यहाँ एक सरल चित्रण है। जैसा कि लिखा गया है, OrderedDictओवरराइड कोड किसी भी वैकल्पिक stream, या कीवर्ड को अनदेखा करता है indent, जो पारित हो सकते हैं, लेकिन उन्हें लागू करने के लिए बढ़ाया जा सकता है। दुर्भाग्य से इस तकनीक का इस तरह के एक के रूप में एक और कंटेनर के अंदर उन्हें संभाल नहीं करता है, के केwidthdepthlistOrderDict

from collections import OrderedDict
from pprint import pprint as pp_pprint

def pprint(obj, *args, **kwrds):
    if not isinstance(obj, OrderedDict):
        # use stock function
        return pp_pprint(obj, *args, **kwrds)
    else:
        # very simple sample custom implementation...
        print "{"
        for key in obj:
            print "    %r:%r" % (key, obj[key])
        print "}"

l = [10, 2, 4]
d = dict((('john',1), ('paul',2), ('mary',3)))
od = OrderedDict((('john',1), ('paul',2), ('mary',3)))
pprint(l, width=4)
# [10,
#  2,
#  4]
pprint(d)
# {'john': 1, 'mary': 3, 'paul': 2}

pprint(od)
# {
#     'john':1
#     'paul':2
#     'mary':3
# }

0

यदि शब्दकोश आइटम सभी एक प्रकार के हैं, तो आप अद्भुत डेटा-हैंडलिंग लाइब्रेरी का उपयोग कर सकते हैं pandas:

>>> import pandas as pd
>>> x = {'foo':1, 'bar':2}
>>> pd.Series(x)
bar    2
foo    1
dtype: int64

या

>>> import pandas as pd
>>> x = {'foo':'bar', 'baz':'bam'}
>>> pd.Series(x)
baz    bam
foo    bar
dtype: object

2
वह कोड क्या करेगा? यहाँ अन्य समाधानों के क्या फायदे हैं?
एलियास ज़मरिया २५'१४
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.