2012-11-10 27 views
13

के साथ वापस लौटें मैं वाईएएमएल डेटा से दस्तावेज़ जेनरेटर बना रहा हूं, जो निर्दिष्ट करेगा कि वाईएएमएल फ़ाइल की कौन सी रेखा प्रत्येक आइटम से उत्पन्न होती है। इसे करने का बेहतरीन तरीका क्या है? तो अगर YAML फ़ाइल इस तरह है:पार्सिंग वाईएएमएल, लाइन नंबर

- key1: item 1 
    key2: item 2 
- key1: another item 1 
    key2: another item 2 

मैं कुछ इस तरह हैं:

[ 
    {'__line__': 1, 'key1': 'item 1', 'key2': 'item 2'}, 
    {'__line__': 3, 'key1': 'another item 1', 'key2': 'another item 2'}, 
] 

मैं वर्तमान में PyYAML उपयोग कर रहा हूँ, लेकिन किसी भी अन्य पुस्तकालय अगर मैं अजगर से उपयोग कर सकते हैं ठीक है।

उत्तर

10

मैं Composer.compose_node और Constructor.construct_mapping को जोड़ने हुक से यह कर दिया है:

import yaml 
from yaml.composer import Composer 
from yaml.constructor import Constructor 

def main(): 
    loader = yaml.Loader(open('data.yml').read()) 
    def compose_node(parent, index): 
     # the line number where the previous token has ended (plus empty lines) 
     line = loader.line 
     node = Composer.compose_node(loader, parent, index) 
     node.__line__ = line + 1 
     return node 
    def construct_mapping(node, deep=False): 
     mapping = Constructor.construct_mapping(loader, node, deep=deep) 
     mapping['__line__'] = node.__line__ 
     return mapping 
    loader.compose_node = compose_node 
    loader.construct_mapping = construct_mapping 
    data = loader.get_single_data() 
    print(data) 
+0

धन्यवाद - यह त्रुटि रिपोर्टिंग की बात आती है और यह बहुत उपयोगी है। –

2

आगे प्रेरणा के लिए, यहाँ इस के लिए मेरे कोड है। इसमें उपर्युक्त अनुरोध से अधिक जानकारी है क्योंकि यह start_mark का उपयोग करके स्थान जानकारी की रिपोर्ट करता है, प्रत्येक dict/list/यूनिकोड पर end_mark (dict_node, list_node, unicode_node subclasses का क्रमशः क्रमशः)।

https://gist.github.com/dagss/5008118

3

आप ruamel.yaml उपयोग कर रहे हैं> = 0.9 (जिनमें से मैं लेखक हूँ), और RoundTripLoader का उपयोग पंक्ति और स्तंभ प्राप्त करने के लिए, आप संग्रह वस्तुओं पर संपत्ति lc उपयोग कर सकते हैं, जहां वे में शुरू स्रोत वाईएएमएल:

def test_item_04(self): 
    data = load(""" 
    # testing line and column based on SO 
    # http://stackoverflow.com/questions/13319067/ 
    - key1: item 1 
     key2: item 2 
    - key3: another item 1 
     key4: another item 2 
     """) 
    assert data[0].lc.line == 2 
    assert data[0].lc.col == 2 
    assert data[1].lc.line == 4 
    assert data[1].lc.col == 2 

(रेखा और कॉलम 0 पर गिनती शुरू करें)।

This answer दिखाएं कि lc लोडिंग के दौरान स्ट्रिंग प्रकारों को विशेषता कैसे जोड़ें।

+0

इस काम को देने का कोई तरीका नहीं मिला अगर सूची किसी ऑर्डर किए गए मानचित्र के अंदर है, जैसे 'key1: !! omap \ n - key4: item2 \ n - key3: item3'' key4' तक पहुंचना संभव नहीं है और 'key3' रेखा संख्याएं। – zezollo

+0

@zezollo एक ऑर्डरमैप डिफ़ॉल्ट रूप से एक टिप्पणी मैप संरचना में लोड नहीं होता है और इसलिए 'lc' विशेषता नहीं होती है। आपको ReplyedMap के उप-वर्ग के रूप में ओमैप लोडिंग पंजीकृत करना होगा। यह करने योग्य है, लेकिन मैं एक टिप्पणी में जवाब दे सकता हूं। यदि आप यह नहीं समझ सकते कि इसे कैसे किया जाए तो आपको एक नया प्रश्न पोस्ट करना चाहिए। – Anthon

+0

वास्तव में मैं इसे समझ नहीं सकता। मुझे लाइन नंबर प्राप्त करने के लिए केवल "गंदा" कामकाज मिला है। प्रश्न पूछा [यहां] (https://stackoverflow.com/questions/45716281/parsing-yaml-get-line-numbers-even-in-ordered-maps)। – zezollo

संबंधित मुद्दे