2012-06-07 41 views
6

tôi biết làm thế nào để làm cho một tập tin .txt ... nhưng bây giờ tôi nhận được một số rắc rối cho một tập tin .csv. Làm thế nào tôi có thể đọc một tập tin csv từ dưới cùng trong python?làm thế nào để đọc một tập tin csv theo thứ tự ngược trong python

+3

[Bạn đã thử gì cho đến nay?] (Http://mattgemmell.com/2008/12/08/what-have-you-tried/) – JoeFish

+2

bạn có đang sử dụng Linux không? 'tac' tệp rồi đọc nó. – dm03514

+0

Hiển thị cho chúng tôi những gì bạn có cho tệp '.txt'.Rất có thể là bạn có thể sử dụng cùng một kỹ thuật. – NPE

Trả lời

19

Khá nhiều cách tương tự như đối với một tập tin văn bản: đọc toàn bộ điều vào một danh sách và sau đó đi ngược:

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

Nếu bạn muốn nhận được ưa thích, bạn có thể viết rất nhiều mã mà đọc khối bắt đầu ở phần cuối của tệp và làm việc ngược, phát ra một dòng tại một thời điểm, sau đó cấp dữ liệu đó cho csv.reader, nhưng điều đó sẽ chỉ hoạt động với tệp có thể tìm kiếm, nghĩa là tệp đĩa chứ không phải đầu vào chuẩn.


Một số người trong chúng ta có tập tin không phù hợp với bộ nhớ, bất cứ ai có thể đi kèm với một giải pháp mà không yêu cầu lưu trữ toàn bộ tập tin trong bộ nhớ?

Đó là một chút phức tạp hơn. May mắn thay, tất cả các yêu cầu csv.reader là một đối tượng giống như trình lặp trả về một chuỗi (dòng) cho mỗi cuộc gọi đến next(). Vì vậy, chúng tôi lấy các kỹ thuật Darius Bacon trình bày trong "Most efficient way to search the last x lines of a file in python" để đọc những dòng của một tập tin ngược, mà không cần phải kéo trong toàn bộ tập tin:

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) 

và thức ăn reversed_lines vào mã để đảo ngược dòng trước họ nhận được để csv.reader, loại bỏ sự cần thiết của reversedlist:

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

có một giải pháp Pythonic nhiều càng tốt, mà không đòi hỏi một nhân vật theo từng ký tự đảo ngược của khối trong bộ nhớ (gợi ý: chỉ nhận được al ist các chỉ mục có dòng kết thúc trong khối, đảo ngược và sử dụng nó để cắt khối) và sử dụng chain trong số itertools để dán các cụm dòng từ các khối liên tiếp lại với nhau, nhưng còn lại như một bài tập cho người đọc.


Nó đáng chú ý là các reversed_lines() thành ngữ trên chỉ hoạt động nếu các cột trong file CSV không chứa ký tự dòng mới.

Aargh! Luôn luôn có điều gì đó. May mắn thay, nó không quá xấu để sửa lỗi này:

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] 

Tất nhiên, bạn sẽ cần phải thay đổi nhân vật báo nếu phương ngữ CSV của bạn không sử dụng ".

+0

có giống nhau không? f = open (FilePath, "rb") csvfile = reversed ([dòng cho dòng trong csv.reader (f)]) – SirC

+0

Bạn không nên dựa vào bộ sưu tập rác để đóng tệp của mình. Điều này sẽ không hoạt động tốt trong việc triển khai Python không sử dụng tính toán tham chiếu để thu thập rác, và nó cũng kích hoạt 'ResourceWarning' trong CPython 3.2 (nếu được kích hoạt). –

+1

Một nhận xét khác: Tôi không thích thành ngữ '[line for line in reader]', và thích 'list (reader)', điều mà tôi cảm thấy là quan trọng hơn. –

0

Xây dựng câu trả lời của @ mike-desimone. Dưới đây là giải pháp cung cấp cấu trúc giống như đối tượng tệp python nhưng được đọc ngược lại, từng dòng:

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

. Đây là chương trình đơn giản để đảo ngược các hàng từ tệp CSV.

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] 
Các vấn đề liên quan