这是一个试图在最短的时间内到达线路并从那里开始的问题。
我有一个巨大的文本文件,我正在阅读并逐行执行操作。我目前正在跟踪我已解析的行号,以便在系统崩溃的情况下,我知道我做了多少。
如果我不想从头开始重新开始,如何重新开始阅读文件。
count = 0
all_parsed = os.listdir("urltextdir/")
with open(filename,"r") as readfile :
for eachurl in readfile:
if str(count)+".txt" not in all_parsed:
urltext = getURLText(eachurl)
with open("urltextdir/"+str(count)+".txt","w") as writefile:
writefile.write(urltext)
result = processUrlText(urltext)
saveinDB(result)
这就是我目前正在做的事情,但是当它崩溃了一百万行时,我不得不通过文件中的所有这些行来达到我想要开始的点,我的其他选择是使用readlines并将整个文件加载到内存中。
有没有我可以考虑的替代方案。
答案 0 :(得分:1)
不幸的是,行号并不是文件对象的基本位置,而next
会破坏特殊的搜索/告知功能,这在loop
中会被调用。你不能跳到一行,但你可以到一个字节位置。所以一种方法是:
line = readfile.readline()
while line:
line = readfile.readline(): #Must use `readline`!
lastell = readfile.tell()
print(lastell) #This is the location of the imaginary cursor in the file after reading the line
print(line) #Do with line what you would normally do
print(line) #Last line skipped by loop
现在您可以轻松地跳回
readfile.seek(lastell) #You need to keep the last lastell)
您需要将lastell
保存到文件或打印,以便重新启动时知道您正在从哪个字节开始。
不幸的是,你不能使用书面文件,因为对字符数量的任何修改都会破坏基于此的计数。
这是一个完整的实现。创建一个名为tell
的文件,并在其中放置0,然后您可以运行:
with open('tell','r+') as tfd:
with open('abcdefg') as fd:
fd.seek(int(tfd.readline())) #Get last position
line = fd.readline() #Init loop
while line:
print(line.strip(),fd.tell()) #Action on line
tfd.seek(0) #Clear and
tfd.write(str(fd.tell())) #write new position only if successful
line = fd.readline() #Advance loop
print(line) #Last line will be skipped by loop
您可以检查这样的文件是否存在,并在程序中创建它。
正如@Edwin在评论中指出的那样,你可能希望fd.flush()
和os.fsync(fd.fileno)
(import os
,如果不清楚),以确保每次写入后你的文件内容都是实际上在磁盘上 - 这将适用于您正在执行的两个写操作,tell
当然更快。这可能会让您大大减慢速度,因此如果您对同步性感到满意,请不要使用它,或只刷新tfd
。您还可以在调用buffer
大小时指定open
,以便Python自动flushes
更快,详见https://stackoverflow.com/a/3168436/6881240。
答案 1 :(得分:0)
如果我做对了, 您可以创建一个简单的日志文件来存储计数。
但仍然会建议使用多个文件或将每个行或段存储在数据库le sql或mongoDB中
答案 2 :(得分:0)
我想这取决于您的脚本运行的系统,以及您可用的资源(如内存)。
但是流行的说法"内存很便宜",你可以简单地将文件读入内存。
作为测试,我创建了一个包含200万行的文件,每行包含1024个字符,代码如下:
ms = 'a' * 1024
with open('c:\\test\\2G.txt', 'w') as out:
for _ in range(0, 2000000):
out.write(ms+'\n')
这导致磁盘上有2 GB的文件。
然后我将文件读入内存中的列表,如下所示:my_file_as_list = [a for a in open('c:\\test\\2G.txt', 'r').readlines()]
我检查了python进程,它在内存中使用了2 GB以上(在32 GB系统上) 访问数据的速度非常快,可以通过列表切片方法完成。
您需要跟踪列表的索引,当系统崩溃时,您可以再次从该索引开始。
但更重要的是......如果你的系统是"崩溃"然后你需要找出崩溃的原因......这几天肯定有几百万行数据不再是崩溃的原因......