在更新文件时使用Python csv模块

时间:2010-01-04 18:19:43

标签: python file csv

我正在使用python的csv模块从csv中提取数据,该数据不断被外部工具更新。我遇到了一个问题,当我到达文件的末尾时,我得到一个StopIteration错误,但是,我希望脚本继续循环,等待外部工具添加更多行。

到目前为止我想出的是:

f = open('file.csv')
csvReader = csv.reader(f, delimiter=',')
while 1:
    try:
        doStuff(csvReader.next())
    except StopIteration:
        depth = f.tell()
        f.close()
        f = open('file.csv')
        f.seek(depth)
        csvReader = csv.reader(f, delimiter=',')

这具有预期的功能,但它看起来也很糟糕。在捕获StopIteration之后循环是不可能的,因为一旦抛出StopIteration,它将在每次后续调用next()时抛出StopIteration。任何人都有任何关于如何实现这一点的建议是这样的,我不必这么愚蠢地告诉和寻求?或者拥有一个可以轻松支持此功能的不同python模块。

3 个答案:

答案 0 :(得分:4)

您的问题不在于CSV阅读器,而在于文件对象本身。您可能仍然需要在上面的代码片段中进行疯狂的旋转,但最好是创建一个文件对象包装器或子类来为您完成,并将其与CSV阅读器一起使用。这使得复杂性与csv处理代码隔离开来。

例如(警告:未经测试的代码):

class ReopeningFile(object):
    def __init__(self, filename):
        self.filename = filename
        self.f = open(self.filename)

    def next(self):
        try:
            self.f.next()
        except StopIteration:
            depth = self.f.tell()
            self.f.close()
            self.f = open(self.filename)
            self.f.seek(depth)
            # May need to sleep here to allow more data to come in
            # Also may need a way to signal a real StopIteration
            self.next()

    def __iter__(self):
        return self

然后您的主代码变得更简单,因为它不必管理文件重新打开(请注意,每当文件重新启动时您也不必重新启动csv_reader:

import csv
csv_reader = csv.reader(ReopeningFile('data.csv'))
for each in csv_reader:
    process_csv_line(each)

答案 1 :(得分:2)

生产者 - 消费者的东西可能会有点棘手。如何使用搜索和读取字节呢?那么使用命名管道呢?

哎呀,为什么不通过本地套接字进行通信?

答案 2 :(得分:0)

您很少需要明确捕获StopIteration。这样做:

for row in csvReader:
    doStuff(row)

至于检测何时将新行写入文件,您可以成为tail -f进程或写出tail -f所做的Python代码。 (它并不复杂;它基本上只是stat每秒一次,以查看它是否被更改。Here's the C source code of tail.

编辑:令人失望的是,popening tail -f无效,正如我在Python 2.x中所预期的那样。看起来迭代文件的行是使用fread和一个大的缓冲区实现的,即使该文件应该是无缓冲的(比如当subprocess.py创建文件时,传递bufsize = 0)。但无论如何,popening tail将是一个温和丑陋的黑客。