Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python转到文本文件行而不读取前面的行_Python - Fatal编程技术网

Python转到文本文件行而不读取前面的行

Python转到文本文件行而不读取前面的行,python,Python,我正在处理一个非常大的文本文件(tsv),大约有2亿条条目。其中一列是日期,记录按日期排序。现在我想开始读取给定日期的记录。目前,我只是从一开始就阅读,速度非常慢,因为我需要阅读近1-1.5亿条记录才能达到这一记录。我在想,如果我可以使用二进制搜索来加速它,我可以在最多28个额外的记录读取(日志(2亿))。python是否允许读取第n行而不缓存或读取其前面的行 如果要读取的文件很大,并且您不想一次读取内存中的整个文件: fp = open("file") for i, line in enume

我正在处理一个非常大的文本文件(tsv),大约有2亿条条目。其中一列是日期,记录按日期排序。现在我想开始读取给定日期的记录。目前,我只是从一开始就阅读,速度非常慢,因为我需要阅读近1-1.5亿条记录才能达到这一记录。我在想,如果我可以使用二进制搜索来加速它,我可以在最多28个额外的记录读取(日志(2亿))。python是否允许读取第n行而不缓存或读取其前面的行

如果要读取的文件很大,并且您不想一次读取内存中的整个文件:

fp = open("file")
for i, line in enumerate(fp):
    if i == 25:
        # 26th line
    elif i == 29:
        # 30th line
    elif i > 29:
        break
fp.close()

请注意,对于第n行,
i==n-1

如果文件的长度不是固定的,那么您就倒霉了。某些函数必须读取该文件。如果文件是固定长度的,可以使用函数
file.seek(line*linesize)
打开文件。然后从那里读取文件。

您可以使用方法
fileObject.seek(offset[,whence])

对于此代码,我使用下一个文件:

100101
101102
102103
103104
104105
105106
106107
107108
108109
109110
110111
python无法跳过文件中的“行”。我所知道的最好的方法是使用生成器根据特定条件生成线,即
date>“YYYY-MM-DD”
。至少这样可以减少内存使用和i/o时间

例如:

# using python 3.4 syntax (parameter type annotation)

from datetime import datetime

def yield_right_dates(filepath: str, mydate: datetime):

    with open(filepath, 'r') as myfile:

        for line in myfile:
        # assume:
        #    the file is tab separated (because .tsv is the extension) 
        #    the date column has column-index == 0
        #    the date format is '%Y-%m-%d'
            line_splt = line.split('\t')
            if datetime.strptime(line_splt[0], '%Y-%m-%d') > mydate:
                yield line_splt

my_file_gen = yield_right_dates(filepath='/path/to/my/file', mydate=datetime(2015,01,01))
# then you can do whatever processing you need on the stream, or put it in one giant list.
desired_lines = [line for line in my_file_gen]
但这仍然将您限制为一个处理器:(

假设您使用的是类unix系统,bash是shell,我会使用shell实用程序
拆分
,然后使用多处理和上面定义的生成器拆分文件

我现在没有一个大文件可供测试,但稍后我将使用一个基准测试更新这个答案,该基准测试是迭代整个文件,而不是拆分文件,然后使用生成器和多处理模块进行迭代


对文件有更深入的了解(例如,如果所有所需日期都聚集在开始|中心|结束处),您可能能够进一步优化读取。

除非您的所有行都具有固定长度,否则Python不能简单地知道行是什么。它必须读取所有内容才能找到表示行结尾的
\n
字符。除非您能够以某种方式计算行结尾的字节偏移量,因为您的数据结构允许这样做,否则没有神奇的解决方法。可能重复@deceze是的,您是正确的,python无法知道“\n”的存在。不幸的是,我当前的文件没有固定的行字节大小。我将记住这一点,以备将来使用。当您知道行的字节大小时,如何跳过行?如果您必须这样做足够多,它可能是worth将tsv转换为数据库(如sqlite)并在感兴趣的列上放置索引。@很难说。显然,导入数据库会带来开销(每个文件一次)。一旦它进入数据库,我猜查询和提取至少会和读取tsv一样快,但我不确定。你应该用虚拟数据制作一个快速原型数据库来找出答案。你能解释一下使用yield有什么帮助吗?
# using python 3.4 syntax (parameter type annotation)

from datetime import datetime

def yield_right_dates(filepath: str, mydate: datetime):

    with open(filepath, 'r') as myfile:

        for line in myfile:
        # assume:
        #    the file is tab separated (because .tsv is the extension) 
        #    the date column has column-index == 0
        #    the date format is '%Y-%m-%d'
            line_splt = line.split('\t')
            if datetime.strptime(line_splt[0], '%Y-%m-%d') > mydate:
                yield line_splt

my_file_gen = yield_right_dates(filepath='/path/to/my/file', mydate=datetime(2015,01,01))
# then you can do whatever processing you need on the stream, or put it in one giant list.
desired_lines = [line for line in my_file_gen]