我正在使用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模块。
答案 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
将是一个温和丑陋的黑客。