2010-01-07 17 views
12

मैं एक CSV फ़ाइल को इस तरह दिखता है:अजगर का CSV पाठक और यात्रा

"Company, Inc.",,,,,,,,,,,,10/30/09 
A/R Summary Aged Analysis Report,,,,,,,,,,,,10:35:01 
All Clients,,,,,,,,,,,,USER 

Client Account,Customer Name,15-Jan,16 - 30,31 - 60,61 - 90,91 - 120,120 - Over,Total,Status,Credit Limit 
1000001111,CLIENT A,0,0,"3,711.32",0,0,"18,629.64","22,340.96",COD,"20,000.00" 
1000002222,CLIENT B,0,0,0,"3,591.27",0,0,"3,591.27",COD,0 
1000003333,CLIENT C,536.78,0,0,0,0,"11,216.60","11,753.38",COD,0 
1000004444,CLIENT D,0,514.94,"3,147.45",690,0,0,"4,352.39",COD,0 

Grand Total,,"139,203,856.06","84,607,749.30","110,746,640.18","58,474,379.45","52,025,869.06","292,653,734.82","737,712,228.87",,,, 

लेकिन मैं केवल लाइन के बाद लाइनों पर कार्रवाई करना चाहते हैं "ग्राहक खाता ..." और "महायोग से पहले .. ।

inputFile = csv.reader(open(filename), dialect='excel') 
records = [line for line in inputFile if line and line[0].isdigit()] 
+1

यह काम करता है। प्रश्न क्या है? –

उत्तर

6
import re 
import StringIO 

data=re.search("Client Account[^\r\n]+[\r\n]+(.*)(?=Grand Total)",open(filename).read(),re.DOTALL).group(1) 
datafile=StringIO.StringIO(data) 

inputFile = csv.reader(datafile, dialect='excel') 
records = [line for line in inputFile if line and line[0].isdigit()] 
+0

मुझे आपका दृष्टिकोण पसंद है, यह तेज़ और सरल है। मैं डेटाफाइल की सामग्री को सूची में कैसे परिवर्तित करूं? – Francis

+0

जब मैंने आपके सुझाव की कोशिश की तो यह त्रुटि संदेश मिला: "टाइप एरर: यूनिकोड को कॉरर्सिंग: स्ट्रिंग या बफर की आवश्यकता है, उदाहरण मिली" – Francis

+0

देरी के लिए खेद है, खुले (डेटाफाइल) को केवल 'डेटाफाइल' होना चाहिए, इसकी पहले से ही फ़ाइल इंस्टेंस अपडेट हो गई है। – YOU

10

आप इस तरह यह कर सकते हैं, झंडा

import csv 
file = "file" 
f=0 
reader = csv.reader(open(file),delimiter=',') 
for row in reader: 
    if "Grand Total" in row: break 
    if "Client Account" in row: f=1;continue 
    if f: 
     if row[0].isdigit(): 
      print row 
की स्थापना द्वारा: "यहाँ कोड है कि अब मैं उपयोग कर रहा हूँ है
+0

संशोधित करें - if "Grand Total" in row: break और, मुझे लगता है कि आपकी निरंतरता 'पाठक में पंक्ति' पर वापस आ जाएगी, कभी भी कुछ भी संसाधित नहीं करेगी। – KevinDTimm

+0

मेरे पास एक बहुत ही समान सवाल है, मेरी "ग्रैंड टोटल" पंक्ति हमेशा "अनुदान कुल" नहीं होती है, यह अन्य फ़ील्ड हो सकती है, लेकिन इससे पहले हमेशा एक खाली पंक्ति होती है। खाली पंक्ति निर्धारित करके मैं लूप को कैसे तोड़ सकता हूं? – LWZ

3

इस तरह के कुछ के लिए एक अच्छा छोटा जनरेटर का उपयोग करें। यह एक थोड़ा और अधिक सामान्यीकृत किया जा सकता है अगर अपनी आवश्यकताओं को बदलने:

def lines_between(source, first, second): 
    for line in source: 
     if line and line[0] == first: 
      break 

    for line in source: 
     if line: and line[0] == second: 
      break 

     if line: # only non-empty lines 
      yield line 

for record in lines_between(inputFile, 'Client Account', 'Grand Total'): 
    # process record 

आप "गैर खाली लाइनों" फिल्टर के लिए स्पष्ट रूप से नहीं पूछा, लेकिन अपने स्वयं के दृष्टिकोण इस कर रहा था तो मुझे लगता है कि आप इसे करना चाहता था। आप "lazily" ऐसे ही पंक्तियों पर कार्रवाई नहीं करना चाहते हैं, लेकिन सिर्फ पहले से बनाया सब कुछ के साथ एक सूची चाहते हैं, ऐसा करते हैं:

records = list(lines_between(inputFile, 'Client Account', 'Grand Total')) 

वैसे, विंडोज पर, वास्तविक खोलने के लिए सुनिश्चित हो बाइनरी मोड का उपयोग कर csv.reader(open(filename, 'rb'), dialect='excel')csv docs note के साथ स्रोत फ़ाइल का उपयोग कर स्रोत फ़ाइल।

12

जनरेटर के माध्यम से। आप साधारण जेनरेटर-फ़िल्टर फ़ंक्शंस से सभी प्रकार की जटिलता बना सकते हैं। जबकि आपके फ़िल्टर की तुलना में काफी जटिल है, यह अधिक एक्स्टेंसिबल है और आसानी से जटिल स्प्रेडशीट को आसानी से संभाल सकता है।

def skip_blank(rdr): 
    for row in rdr: 
     if len(row) == 0: continue 
     if all(len(col)==0 for col in row): continue 
     yield row 

def after_heading(text, rdr): 
    i= iter(rdr) 
    for row in i: 
     if any(column == text for column in row): 
      break 
    for row in i: 
     yield row 

def before_footing(text, rdr): 
    for row in rdr: 
     if any(column == text for column in row): 
      break 
     yield row 

def between(start, end, rdr): 
    for row in before_footing(end, after_heading(start, rdr)): 
     yield row 

for row in between('Grand Total', 'Client Account', skip_blank(inputFile)): 
    print row 
संबंधित मुद्दे