python csv扭曲

2024-10-03 06:26:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图找到一个百分比,当我阅读csv文件。我知道如何使用tell()对file对象执行此操作,但是当我使用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()在启动for循环之前确实返回0。在

这将为我的csv文件中的每一行返回相同的结果: 579/579 | 0

我做错什么了?在


Tags: 文件csvcsvfile对象函数posforsize
2条回答

csvreader文档说:

... csvfile can be any object which supports the iterator protocol and returns a string each time its next() method is called ...

因此,对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

在我的测试数据上运行这个程序可以得到以下结果,表明这两种不同的方法会产生不同的结果。在

^{pr2}$

我在open上设置了零缓冲,但这没什么区别,问题是{}在生成器中。在

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处理,因此您也可以利用您打开的文件来实现这一点。我不确定以内存映射的形式打开文件,然后再次将其作为普通文件读取是否会有更好的效果。在

相关问题 更多 >