16

TXTファイルに対してそれを行う方法を知っていますが、CSVファイルに対してそれを行うのに問題があります。

PythonでCSVファイルを下から読み取るにはどうすればよいですか?

4

3 に答える 3

37

テキストファイルの場合とほぼ同じ方法です。すべてをリストに読み込んでから、逆方向に移動します。

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

ファンシーになりたい場合は、ファイルの最後から逆方向にブロックを読み取り、一度に1行ずつ出力し、それをにフィードする多くのコードを記述できますが、これは次のファイルでcsv.readerのみ機能します。シークできます。つまり、ディスクファイルですが、標準入力ではありません。


私たちの中にはメモリに収まらないファイルを持っている人もいますが、ファイル全体をメモリに保存する必要のないソリューションを誰かが思いつくことができますか?

それは少しトリッキーです。幸いなことに、すべてのcsv.reader期待は、への呼び出しごとに文字列(行)を返すイテレータのようなオブジェクトですnext()そこで、「 Pythonでファイルの最後のx行を検索する最も効率的な方法」で示したDarius Baconの手法を利用して、ファイル全体をプルすることなく、ファイルの行を逆方向に読み取ります。

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.readerreversedlist

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

よりPythonicな解決策があります。これは、メモリ内のブロックを文字ごとに反転する必要がありません(ヒント:ブロック内に行末があるインデックスのリストを取得し、それを反転して、次のように使用します。ブロックをスライスします)、およびを使用chainして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方言でを使用しない場合は、引用文字を変更する必要があります"

于 2012-06-07T14:33:55.717 に答える
1

@mike-desimoneの答えに基づいて構築します。これは、Pythonファイルオブジェクトと同じ構造を提供するが、行ごとに逆に読み取られるソリューションです。

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]
于 2015-08-07T02:23:09.050 に答える
0

頑張れ。これは、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]
于 2017-06-22T10:51:29.390 に答える