2013-02-16 50 views
5

कई प्रोग्रामिंग भाषाओं की मानक लाइब्रेरी में टेक्स्ट इनपुट स्ट्रीम से तार, संख्या या अन्य ऑब्जेक्ट निकालने के लिए "स्कैनर एपीआई" शामिल है। (उदाहरण के लिए, जावा में Scanner वर्ग शामिल है, सी ++ में istream शामिल है, और सी में scanf शामिल है)।पायथन स्ट्रीम एक्सट्रैक्शन

पायथन में इसके बराबर क्या है?

पायथन में एक स्ट्रीम इंटरफ़ेस है, यानी io.IOBase से प्राप्त कक्षाएं। हालांकि, पायथन TextIOBase स्ट्रीम इंटरफ़ेस केवल लाइन उन्मुख इनपुट के लिए सुविधाएं प्रदान करता है। reading the documentation और searching on Google के बाद, मुझे मानक पायथन मॉड्यूल में कुछ नहीं मिल रहा है जो मुझे उदाहरण देगा, उदाहरण के लिए, टेक्स्ट स्ट्रीम से एक पूर्णांक निकालें, या स्ट्रिंग के रूप में अगली स्पेस-सीमांकित शब्द निकालें। क्या ऐसा करने के लिए कोई मानक सुविधाएं हैं?

+0

यदि इनपुट बहुत गंदा/मनमाना है, तो मैं 'पुनः' मॉड्यूल का उपयोग करता हूं; अगर इनपुट संरचित किया गया है तो मैं सरल पार्सल जैसी एक पार्सर लाइब्रेरी पसंद करता हूं (नियमित अभिव्यक्तियों से ईबीएनएल को बनाए रखना आसान है)। –

+1

यदि आपके पास दिमाग में उपयोग का मामला है, तो शायद सामान्य पूछताछ करने के बजाय आपके प्रश्न को अपडेट करने के लिए यह अधिक उत्पादक होगा। –

+0

कुछ अन्य सुझावों के लिए http://stackoverflow.com/questions/2175080/sscanf-in-python देखें। –

उत्तर

3

fscanf या जावा के Scanner के बराबर नहीं है। सबसे सरल समाधान उपयोगकर्ता को अंतरिक्ष से अलग इनपुट के बजाय न्यूलाइन सेपरेटेड इनपुट का उपयोग करने की आवश्यकता है, फिर आप रेखा से रेखा को पढ़ सकते हैं और लाइनों को सही प्रकार में बदल सकते हैं।

यदि आप चाहते हैं कि उपयोगकर्ता अधिक संरचित इनपुट प्रदान करे तो आपको शायद उपयोगकर्ता इनपुट के लिए एक पार्सर बनाना चाहिए। पाइथन के लिए कुछ अच्छी पार्सिंग लाइब्रेरी हैं, उदाहरण के लिए pyparsing। 200812 का अंतिम अपडेट भी है, भले ही scanf मॉड्यूल भी है।

यदि आप बाह्य निर्भरता नहीं चाहते हैं तो आप इनपुट अनुक्रमों से मेल खाने के लिए रेगेक्स का उपयोग कर सकते हैं। निश्चित रूप से regexes तारों पर काम करने की आवश्यकता है, लेकिन आप आसानी से इस सीमा पढ़ने में भाग ले सकते हैं। उदाहरण के लिए कुछ इस तरह अच्छी तरह से समय की सबसे काम करना चाहिए:

import re 


FORMATS_TYPES = { 
    'd': int, 
    'f': float, 
    's': str, 
} 


FORMATS_REGEXES = {  
    'd': re.compile(r'(?:\s|\b)*([+-]?\d+)(?:\s|\b)*'), 
    'f': re.compile(r'(?:\s|\b)*([+-]?\d+\.?\d*)(?:\s|\b)*'), 
    's': re.compile(r'\b(\w+)\b'), 
} 


FORMAT_FIELD_REGEX = re.compile(r'%(s|d|f)') 


def scan_input(format_string, stream, max_size=float('+inf'), chunk_size=1024): 
    """Scan an input stream and retrieve formatted input.""" 

    chunk = '' 
    format_fields = format_string.split()[::-1] 
    while format_fields: 
     fields = FORMAT_FIELD_REGEX.findall(format_fields.pop()) 
     if not chunk: 
      chunk = _get_chunk(stream, chunk_size) 

     for field in fields: 
      field_regex = FORMATS_REGEXES[field] 
      match = field_regex.search(chunk) 
      length_before = len(chunk) 
      while match is None or match.end() >= len(chunk): 
       chunk += _get_chunk(stream, chunk_size) 
       if not chunk or length_before == len(chunk): 
        if match is None: 
         raise ValueError('Missing fields.') 
        break 
      text = match.group(1) 
      yield FORMATS_TYPES[field](text) 
      chunk = chunk[match.end():] 



def _get_chunk(stream, chunk_size): 
    try: 
     return stream.read(chunk_size) 
    except EOFError: 
     return '' 

उदाहरण उपयोग:

>>> s = StringIO('1234 Hello World -13.48 -678 12.45') 
>>> for data in scan_input('%d %s %s %f %d %f', s): print repr(data) 
...                        
1234                       
'Hello' 
'World' 
-13.48 
-678 
12.45 

आप शायद इस का विस्तार, और यह ठीक से परीक्षण करने के लिए होगा, लेकिन यह आप कुछ विचार देना चाहिए ।

1

कोई प्रत्यक्ष समकक्ष नहीं है (जहां तक ​​मुझे पता है)। हालांकि, आप नियमित अभिव्यक्तियों के साथ बहुत कुछ कर सकते हैं (re मॉड्यूल देखें)।

उदाहरण के लिए:

# matching first integer (space delimited) 
re.match(r'\b(\d+)\b',string) 

# matching first space delimited word 
re.match(r'\b(\w+)\b',string) 

# matching a word followed by an integer (space delimited) 
re.match(r'\b(\w+)\s+(\d+)\b',string) 

यह सामान्य सी-शैली स्कैनर इंटरफ़ेस की तुलना में थोड़ा अधिक काम की आवश्यकता है, लेकिन यह भी बहुत लचीला और शक्तिशाली है। यद्यपि आपको स्ट्रीम I/O स्वयं को संसाधित करना होगा।