2012-02-01 15 views
5

में json.dumps() का उपयोग कर हेक्स स्ट्रिंग के रूप में पूर्णांक मुद्रित करने के लिए कैसे वर्तमान में मैं एक बड़े डेटा संरचना मुद्रित करने के लिएअजगर

print(json.dumps(data, indent=4)) 

निम्नलिखित कोड का उपयोग कर रहा मैं चाहते हैं कि सभी पूर्णांकों में मुद्रित करने के देखने के लिए दशमलव के बजाय हेक्स। क्या यह संभव है? ऐसा लगता है कि पूर्णांक के लिए मौजूदा एन्कोडर को ओवरराइड करने का कोई तरीका नहीं है। आप केवल JSONEncoder क्लास द्वारा पहले से प्रबंधित नहीं किए गए प्रकारों के लिए एक डिफ़ॉल्ट प्रदान कर सकते हैं, लेकिन यह पूर्णांक को एन्कोड करने के तरीके को ओवरराइड करने का कोई तरीका नहीं है।

मुझे लगा कि मैं sys.displayhook का उपयोग कर डिफ़ॉल्ट पूर्णांक मुद्रण व्यवहार को ओवरराइड कर सकता हूं यदि मैं कमांड लाइन में चल रहा था लेकिन मैं नहीं हूं।

बस संदर्भ के लिए डेटा संरचना डिक्ट्स, सूचियों, तारों, इंक आदि का मिश्रण बैग है इसलिए मैं json.dumps() के साथ गया था। ऐसा करने का एकमात्र अन्य तरीका यह है कि मैं इसे स्वयं पार्स करना चाहता हूं और फिर मैं जेसन मॉड्यूल को फिर से लिखूंगा।

अद्यतन: तो मैं कार्यों कि अभी सब पूर्णांक प्रकार हेक्स तार करने के लिए परिवर्तित के साथ मूल डेटा संरचना की एक प्रति प्रिंट serializing के साथ इसे लागू करने समाप्त हो गया:

def odprint(self, hexify=False): 
    """pretty print the ordered dictionary""" 
    def hexify_list(data): 
     _data = [] 
     for i,v in enumerate(data): 
      if isinstance(v, (int,long)): 
       _data.insert(i,hex(v)) 
      elif isinstance(v,list): 
       _data.insert(i, hexify_list(v)) 
      else: 
       _data.insert(i, val) 
     return _data 

    def hexify_dict(data): 
     _data = odict() 
     for k,v in data.items(): 
      if isinstance(v, (dict,odict)): 
       _data[k] = hexify_dict(v) 
      elif isinstance(v, (int, long)): 
       _data[k] = hex(v) 
      elif isinstance(v,list): 
       _data[k] = hexify_list(v) 
      else: 
       _data[k] = v 
     return _data 

    if hexify: 
     print(json.dumps(hexify_dict(self), indent=4)) 
    else: 
     print(json.dumps(self, indent=4)) 

मदद के लिए धन्यवाद। मुझे एहसास है कि मैं एक मानक निर्देश से नाराज हो जाता हूं, लेकिन प्रिंटिंग के लिए यह सिर्फ इतना है कि मुझे जो चाहिए वह ठीक है।

+0

[जेएसओएन में ऑक्टल और हेक्स रूपों की अनुमति नहीं है] (http://tools.ietf.org/html/rfc4627#section-2.4) – jfs

+0

नोट: आपका हेक्साइफ़ _ *() फ़ंक्शन डेटा खो सकता है। यदि आप इस सड़क पर जाते हैं तो आप [कुछ ऐसा] (http://ideone.com/G2DJG) – jfs

+0

का उपयोग कर सकते हैं क्या आप समझा सकते हैं कि यह डेटा कैसे खो सकता है? – Plazgoth

उत्तर

2

एक संभावित दृष्टिकोण serialize फ़ंक्शन होना है, जो आपके डिक्शनरी की एक प्रति उत्पन्न करता है फ्लाई पर वाई और स्ट्रिंग को डंप करने के लिए मानक json मॉड्यूल का उपयोग करता है। एक प्रारंभिक कार्यान्वयन लगता है:

import json 

def serialize(data): 
    _data = {} 
    for k, v in data.items(): 
     if isinstance(v, int): 
      _data[k] = hex(v) 
     else: 
      _data[k] = v 
    return json.dumps(_data, indent=4) 


if __name__ == "__main__": 
    data = {"a":1, "b":2.0, "c":3} 
    print serialize(data) 

उत्पादन:

{ 
    "a": "0x1", 
    "c": "0x3", 
    "b": 2.0 
} 

सूचना है कि इस प्रारंभिक कार्यान्वयन सूचियों के साथ काम नहीं करता है, लेकिन यह आसानी से बदला गया है।

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

चीयर्स।

+0

आप इस काम को सूचियों के साथ कैसे बनायेंगे? – Plazgoth

+0

स्मृति तर्क मेरे मामले में मान्य नहीं है। तो मुझे यह दृष्टिकोण पसंद है। मैं इसका परीक्षण कर रहा हूं और यह पता लगाने की कोशिश कर रहा हूं कि इसे सूचियों और सूचियों की सूची के लिए कैसे काम करना है। मेरी डेटा संरचना बहुत बड़ी नहीं है लेकिन यह बदसूरत है :) – Plazgoth

1

आप मौजूदा एन्कोडर को पूर्णांक के लिए ओवरराइड नहीं कर सकते ... लेकिन आप जो चाहते हैं उसे प्राप्त करने का एक और तरीका हो सकता है। क्या कुछ इस तरह के बारे में:

{ 
    "test": 0x21, 
    "this": 0x63, 
    "something bigger": [ 
     0x1, 
     0x2, 
     0x3, 
     { 
      "a": 0x2c 
     } 
    ] 
} 

नोट:: में

import json 
import re 

data = {'test': 33, 'this': 99, 'something bigger':[1,2,3, {'a':44}]} 
s = json.dumps(data, indent=4) 
print(re.sub('(\d+)', lambda i: hex(int(i.group(0))),s)) 

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

+0

धन्यवाद यह आशाजनक लग रहा है, मैं इसे पचता हूं, इसका परीक्षण करता हूं और आपको वापस ले जाता हूं। – Plazgoth

+0

तो यह काम करता है लेकिन यह संख्याओं को परिवर्तित करता है जब भी वे 'x86_64'' x0x54_0x40 'जैसी स्ट्रिंग का हिस्सा होते हैं, मैंने नियमित अभिव्यक्ति के साथ कुछ मिनट बिताए और इसे ठीक करने के लिए बिताया लेकिन छोड़ दिया :) – Plazgoth

0

अजगर 2.7 के लिए गंदा हैक, मैं इसका इस्तेमाल करने की सिफारिश नहीं होगा:

import __builtin__ 

_orig_str = __builtin__.str 

def my_str(obj): 
    if isinstance(obj, (int, long)): 
     return hex(obj) 
    return _orig_str(obj) 
__builtin__.str = my_str 

import json 

data = {'a': [1,2,3], 'b': 4, 'c': 16**20} 
print(json.dumps(data, indent=4)) 

आउटपुट:

{ 
    "a": [ 
     0x1, 
     0x2, 
     0x3 
    ], 
    "c": 0x100000000000000000000L, 
    "b": 0x4 
} 

अजगर 3 __builtin__ मॉड्यूल अब builtins है, लेकिन मैं परीक्षण नहीं कर सकते यह (ideone.com ImportError के साथ विफल रहता है: libz.so.1 ...)

+0

मैं पायथन 2.6 का उपयोग कर रहा हूं वर्तमान में। लेकिन विचार के लिए धन्यवाद। – Plazgoth

2

ऑक्टल और हेक्साडेसिमल प्रारूप JSON में समर्थित नहीं हैं।

आप इसके बजाय YAML का उपयोग कर सकते हैं।

>>> import json, yaml 
>>> class hexint(int): 
...  def __str__(self): 
...   return hex(self) 
... 
>>> json.dumps({"a": hexint(255)}) 
'{"a": 0xff}' 
>>> yaml.load(_) 
{'a': 255} 

या लपेटकर पूर्णांकों के बिना:

import yaml 

def hexint_presenter(dumper, data): 
    return dumper.represent_int(hex(data)) 
yaml.add_representer(int, hexint_presenter) 

print yaml.dump({"a": 255}), # -> {a: 0xff} 
assert yaml.load('{a: 0xff}') == {"a": 255} 
+0

याम मैं जिस सर्वर का उपयोग कर रहा हूं उस पर पाइथन इंस्टॉलेशन का हिस्सा नहीं है, और मैं अब मॉड्यूल को स्थानीय रूप से जोड़ना नहीं चाहता हूं। लेकिन यह अच्छा लग रहा है। – Plazgoth

+0

@Plazgoth: आप [हेक्सडेसिमल संख्या जेसन के साथ पूर्णांक के रूप में लोड करने में सक्षम नहीं होंगे] (http://ideone.com/cInsT)। – jfs

+0

आह, मैं आपकी टिप्पणी समझता हूं। मैं वास्तव में जेसन के रूप में इसका आउटपुट आयात नहीं कर रहा हूं। यह एक मानव पठनीय फैशन में stdout करने के लिए डेटा संरचना मुद्रित करने का एक प्रयास है। धन्यवाद, मुझे यह कहना चाहिए था कि मेरे प्रश्न में। – Plazgoth

0

तुम हमेशा json है, जहां आप पूर्णांक पार्स पर कुछ नियंत्रण है Reparse सकता है, ताकि आप पूर्णांक रेपर ओवरराइड कर सकते हैं:

class hexint(int): 
    def __repr__(self): 
    return "0x%x" % self 

json.loads(json.dumps(data), parse_int=hexint) 

और data का उपयोग जेराट के उत्तर में करते हुए, आउटपुट है:

{u'test': 0x21, u'this': 0x63, u'something bigger': [0x1, 0x2, 0x3, {u'a': 0x2c}]} 
0

एक-लाइनर

आप अपने हेक्स तार कोई आपत्ति नहीं है उद्धृत किया, इस एक लाइनर का उपयोग करें:

print(json.dumps(eval(str(json.loads(json.dumps(data), parse_int=lambda i:hex(int(i))))), indent=4)) 

आउटपुट (Gerrat के data फिर से उपयोग करते हुए):

{ 
    "test": "0x21", 
    "this": "0x63", 
    "something bigger": [ 
     "0x1", 
     "0x2", 
     "0x3", 
     { 
      "a": "0x2c" 
     } 
    ] 
} 

यह मेरी पिछली पोस्ट की तुलना में एक बेहतर उत्तर है क्योंकि मैंने एक सुंदर मुद्रित परिणाम प्राप्त करने का निपटाया है।

+0

यह ठीक काम करता है, हालांकि यह आदेश में आदेश नहीं रखता है जो आदेश दिया गया है। – Plazgoth