我正在尝试查找通过csv文件阅读时的百分比。我知道如何使用带有文件对象的tell(),但是当我使用csv.reader读取该文件对象,然后对我的reader对象中的行执行for循环时,tell()函数总是返回,就好像它位于文件的末尾,无论我在循环中的哪个位置。我怎样才能找到自己的位置?
当前代码:
with open(FILE_PERSON, 'rb') as csvfile:
spamreader = csv.reader(csvfile)
justtesting = csvfile.tell()
size = os.fstat(csvfile.fileno()).st_size
for row in spamreader:
pos = csvfile.tell()
print pos, "of", size, "|", justtesting
我在那里扔了“justtesting”只是为了证明tell()确实返回0直到我开始我的for循环。
这将为我的csv文件中的每一行返回相同的内容: 579的579 | 0
我做错了什么?
答案 0 :(得分:3)
csv
库在读取文件时使用缓冲区,因此文件指针会以较大的块跳转。它不逐行读取您的文件。
它以较大的块读取数据以使解析更容易,并且由于换行符可以嵌入引号中,因此逐行读取CSV数据将无法正常工作。
如果 要提供进度报告,则需要预先计算行数。以下内容仅在您的输入CSV文件未在列值中嵌入换行符时才有效:
with open(FILE_PERSON, 'rb') as csvfile:
linecount = sum(1 for _ in csvfile)
csvfile.seek(0)
spamreader = csv.reader(csvfile)
for line, row in enumerate(spamreader):
print '{} of {}'.format(line, linecount)
还有其他方法可以计算行数(请参阅How to get line count cheaply in Python?),但由于您将正在阅读文件 以将其作为CSV处理,因此您可以制作使用您拥有的打开文件。我不确定将文件作为内存映射打开,然后将其作为普通文件再次读取将会更好。
答案 1 :(得分:0)
csvreader
文档说:
... csvfile可以是任何支持迭代器协议的对象,每次调用next()方法时都会返回一个字符串......
因此对OP的原始代码进行了少量更改:
import csv
import os
filename = "tar.data"
with open(filename, 'rb') as csvfile:
spamreader = csv.reader(csvfile)
justtesting = csvfile.tell()
size = os.fstat(csvfile.fileno()).st_size
for row in spamreader:
pos = csvfile.tell()
print pos, "of", size, "|", justtesting
###############################################
def generator(csvfile):
# readline seems to be the key
while True:
line = csvfile.readline()
if not line:
break
yield line
###############################################
print
with open(filename, 'rb', 0) as csvfile:
spamreader = csv.reader(generator(csvfile))
justtesting = csvfile.tell()
size = os.fstat(csvfile.fileno()).st_size
for row in spamreader:
pos = csvfile.tell()
print pos, "of", size, "-", justtesting
针对我的测试数据运行此操作会得到以下结果,表明两种不同的方法会产生不同的结果。
224 of 224 | 0
224 of 224 | 0
224 of 224 | 0
224 of 224 | 0
224 of 224 | 0
224 of 224 | 0
224 of 224 | 0
224 of 224 | 0
224 of 224 | 0
224 of 224 | 0
224 of 224 | 0
224 of 224 | 0
224 of 224 | 0
224 of 224 | 0
16 of 224 - 0
32 of 224 - 0
48 of 224 - 0
64 of 224 - 0
80 of 224 - 0
96 of 224 - 0
112 of 224 - 0
128 of 224 - 0
144 of 224 - 0
160 of 224 - 0
176 of 224 - 0
192 of 224 - 0
208 of 224 - 0
224 of 224 - 0
我在open
上设置了零缓冲,但它没有任何区别,生成器中的东西是readline
。