2012-06-07 8 views
6

में रिवर्स ऑर्डर में सीएसवी फ़ाइल को कैसे पढ़ा जाए, मुझे पता है कि .txt फ़ाइल के लिए कैसे करना है ... लेकिन अब मुझे .csv फ़ाइल के लिए कुछ परेशानीएं मिलती हैं। मैं पायथन में नीचे से एक सीएसवी फ़ाइल कैसे पढ़ सकता हूं?पाइथन

+3

[क्या आप अब तक की कोशिश की?] (Http://mattgemmell.com/2008/12/08/what-have-you-tried/) – JoeFish

+2

आप लिनक्स पर कर रहे हैं? फाइल को टैक करें फिर इसे पढ़ें। – dm03514

+0

हमें दिखाएं कि आपको '.txt' फ़ाइल के लिए क्या मिला है।संभावना है कि आप एक ही तकनीक का उपयोग कर सकते हैं। – NPE

उत्तर

19

एक पाठ फ़ाइल के लिए के रूप में सुंदर ज्यादा एक ही तरीके: एक सूची में पूरी बात पढ़ें और फिर पीछे की ओर जाना:

import csv 
with open('test.csv', 'r') as textfile: 
    for row in reversed(list(csv.reader(textfile))): 
     print ', '.join(row) 

आप कल्पना प्राप्त करना चाहते हैं, तो आप जिस पर लिखा कोड का एक बहुत कुछ लिख सकता है फ़ाइल के अंत में शुरू होने वाले ब्लॉक और पीछे की ओर काम करते हुए, एक समय में एक लाइन उत्सर्जित करते हैं, और फिर csv.reader पर फ़ीड करते हैं, लेकिन यह केवल उस फ़ाइल के साथ काम करेगा जिसे खोजा जा सकता है, यानी डिस्क फाइलें लेकिन मानक इनपुट नहीं।


हम में से कुछ फ़ाइलों को स्मृति में फिट नहीं बैठते है, किसी को भी एक समाधान स्मृति में पूरी फ़ाइल भंडारण की आवश्यकता नहीं है कि के साथ आ सकता है?

यह थोड़ा सा ट्रिकियर है। सौभाग्य से, सभी csv.reader अपेक्षाएं एक इटरेटर-जैसी ऑब्जेक्ट है जो next() पर प्रति कॉल एक स्ट्रिंग (लाइन) देता है। इसलिए हम तकनीक Darius बेकन एक फ़ाइल पीछे की ओर की तर्ज पढ़ने के लिए "Most efficient way to search the last x lines of a file in python" में प्रस्तुत हड़पने, पूरी फ़ाइल में खींचने के लिए बिना:

import os 

def reversed_lines(file): 
    "Generate the lines of file in reverse order." 
    part = '' 
    for block in reversed_blocks(file): 
     for c in reversed(block): 
      if c == '\n' and part: 
       yield part[::-1] 
       part = '' 
      part += c 
    if part: yield part[::-1] 

def reversed_blocks(file, blocksize=4096): 
    "Generate blocks of file's contents in reverse order." 
    file.seek(0, os.SEEK_END) 
    here = file.tell() 
    while 0 < here: 
     delta = min(blocksize, here) 
     here -= delta 
     file.seek(here, os.SEEK_SET) 
     yield file.read(delta) 

और कोड में reversed_lines फ़ीड लाइनों को उल्टा करने के से पहले वे csv.reader के लिए मिलता है, reversed और list के लिए की जरूरत को हटाने:

import csv 
with open('test.csv', 'r') as textfile: 
    for row in csv.reader(reversed_lines(textfile)): 
     print ', '.join(row) 

वहाँ एक और अधिक pythonic समाधान संभव है, जो स्मृति में संकेत ब्लॉक के एक चरित्र-दर-चरित्र उत्क्रमण की आवश्यकता नहीं है (है: बस मिल अल इंडेक्स का आईएसटी जहां ब्लॉक में रेखा समाप्त होती है, इसे उलट देती है, और ब्लॉक को टुकड़ा करने के लिए इसका उपयोग करती है), और से itertools का उपयोग करता है ताकि लाइन क्लस्टर को लगातार ब्लॉक से चिपकाया जा सके, लेकिन पाठक के लिए एक अभ्यास के रूप में छोड़ा गया है।


यह ध्यान देने योग्य है कि reversed_lines() ऊपर मुहावरा तभी काम करता है CSV फ़ाइल में स्तंभों नई पंक्तियां शामिल नहीं है लायक है।

आर्ग! हमेशा कुछ है। सौभाग्य से, यह इसे ठीक करने के बहुत बुरा नहीं है:

def reversed_lines(file): 
    "Generate the lines of file in reverse order." 
    part = '' 
    quoting = False 
    for block in reversed_blocks(file): 
     for c in reversed(block): 
      if c == '"': 
       quoting = not quoting 
      elif c == '\n' and part and not quoting: 
       yield part[::-1] 
       part = '' 
      part += c 
    if part: yield part[::-1] 
बेशक

, आप उद्धरण कैरेक्टर को बदलने के लिए करता है, तो अपनी CSV बोली " उपयोग नहीं करता है की आवश्यकता होगी।

+0

क्या यह वही है? एफ = ओपन (फाइलपाथ, "आरबी") csvfile = उलट ([csv.reader (f) में लाइन के लिए लाइन]) – SirC

+0

आपको अपनी फ़ाइलों को बंद करने के लिए कचरा संग्रह पर भरोसा नहीं करना चाहिए। यह पायथन कार्यान्वयन में बहुत अच्छी तरह से काम नहीं करेगा जो कचरा संग्रह के लिए संदर्भ गिनती का उपयोग नहीं कर रहे हैं, और यह 'संसाधन वॉर्निंग' को सीपीथॉन 3.2 (यदि सक्षम है) में भी ट्रिगर करता है। –

+1

एक और टिप्पणी: मुझे '[पाठक में लाइन के लिए लाइन] 'idiom पसंद नहीं है, और' सूची (पाठक) 'पसंद करते हैं, जो मुझे लगता है कि इस बिंदु पर अधिक है। –

0

@ माइक-डेसिमोन के उत्तर पर बिल्डिंग। इसके लिए

import os 

class ReversedFile(object): 
    def __init__(self, f, mode='r'): 
     """ 
     Wraps a file object with methods that make it be read in reverse line-by-line 

     if ``f`` is a filename opens a new file object 

     """ 
     if mode != 'r': 
      raise ValueError("ReversedFile only supports read mode (mode='r')") 

     if not type(f) == file: 
      # likely a filename 
      f = open(f) 

     self.file = f 
     self.lines = self._reversed_lines() 

    def _reversed_lines(self): 
     "Generate the lines of file in reverse order." 
     part = '' 
     for block in self._reversed_blocks(): 
      for c in reversed(block): 
       if c == '\n' and part: 
        yield part[::-1] 
        part = '' 
       part += c 
     if part: yield part[::-1] 

    def _reversed_blocks(self, blocksize=4096): 
     "Generate blocks of file's contents in reverse order." 
     file = self.file 

     file.seek(0, os.SEEK_END) 
     here = file.tell() 
     while 0 < here: 
      delta = min(blocksize, here) 
      here -= delta 
      file.seek(here, os.SEEK_SET) 
      yield file.read(delta) 


    def __getattribute__(self, name): 
     """ 
     Allows for the underlying file attributes to come through 

     """ 
     try: 
      # ReversedFile attribute 
      return super(ReversedFile, self).__getattribute__(name) 
     except AttributeError: 
      # self.file attribute 
      return getattr(self.file, name) 

    def __iter__(self): 
     """ 
     Creates iterator 

     """ 
     return self 

    def seek(self): 
     raise NotImplementedError('ReversedFile does not support seek') 

    def next(self): 
     """ 
     Next item in the sequence 

     """ 
     return self.lines.next() 

    def read(self): 
     """ 
     Returns the entire contents of the file reversed line by line 

     """ 
     contents = '' 

     for line in self: 
      contents += line 

     return contents 

    def readline(self): 
     """ 
     Returns the next line from the bottom 

     """ 
     return self.next() 

    def readlines(self): 
     """ 
     Returns all remaining lines from the bottom of the file in reverse 

     """ 
     return [x for x in self] 
0

जाओ: यहाँ एक समाधान है कि एक अजगर फ़ाइल वस्तु के रूप में एक ही संरचना प्रदान करता है, लेकिन लाइन द्वारा रिवर्स, लाइन में पढ़ रहा है। यह एक सीएसवी फ़ाइल से पंक्तियों को उलट करने के लिए सरल कार्यक्रम है।

import csv 
BC_file = open('Master.csv', 'rb') 
BC_reader = csv.reader(BC_file) 
next(BC_reader) 
for row in reversed(list(BC_reader)): 
    print row[0]