我有一个22mb的文本文件,其中包含一个数字列表(每行1个数字)。我试图让python读取数字,处理数字并将结果写入另一个文件。所有这一切都有效但如果我必须停止程序,它从头开始。我一开始尝试使用mysql数据库但速度太慢了。我通过这种方式处理的数量大约是4倍。我希望能够在处理号码后删除该行。
with open('list.txt', 'r') as file:
for line in file:
filename = line.rstrip('\n') + ".txt"
if os.path.isfile(filename):
print "File", filename, "exists, skipping!"
else:
#process number and write file
#(need code to delete current line here)
正如您每次重新启动时所看到的那样,它必须在硬盘驱动器中搜索文件名,以确保它到达它停止的位置。有150万个数字,这可能需要一段时间。我找到了一个截断的例子,但它没有用。
是否有类似于array_shift(PHP)的命令用于python,它们将与文本文件一起使用。
答案 0 :(得分:7)
我会使用标记文件来保留最后一行的编号,而不是重写输入文件:
start_from = 0
try:
with open('last_line.txt', 'r') as llf: start_from = int(llf.read())
except:
pass
with open('list.txt', 'r') as file:
for i, line in enumerate(file):
if i < start_from: continue
filename = line.rstrip('\n') + ".txt"
if os.path.isfile(filename):
print "File", filename, "exists, skipping!"
else:
pass
with open('last_line.txt', 'w') as outfile: outfile.write(str(i))
此代码首先检查文件last_line.txt并尝试从中读取一个数字。该数字是在上一次尝试期间处理的行数。然后它只是跳过所需的行数。
答案 1 :(得分:1)
我使用Redis这样的东西。安装redis然后安装pyredis你可以在内存中拥有一个持久集。然后你可以这样做:
r = redis.StrictRedis('localhost')
with open('list.txt', 'r') as file:
for line in file:
if r.sismember('done', line):
continue
else:
#process number and write file
r.sadd('done', line)
如果您不想安装Redis,您也可以使用shelve模块,确保使用writeback = False选项打开它。我真的推荐Redis,它让这样的事情变得如此简单。
答案 2 :(得分:1)
读取数据文件不应该成为瓶颈。以下代码在我的机器上大约0.2秒读取36 MB,697997行文本文件:
import time
start = time.clock()
with open('procmail.log', 'r') as f:
lines = f.readlines()
end = time.clock()
print 'Readlines time:', end-start
因为它产生了以下结果:
Readlines time: 0.1953125
请注意,此代码一次性生成一个行列表。
要知道您去过的地方,只需将已处理的行数写入文件即可。然后,如果你想再试一次,请阅读所有的行并跳过你已经完成的行:
import os
# Raad the data file
with open('list.txt', 'r') as f:
lines = f.readlines()
skip = 0
try:
# Did we try earlier? if so, skip what has already been processed
with open('lineno.txt', 'r') as lf:
skip = int(lf.read()) # this should only be one number.
del lines[:skip] # Remove already processed lines from the list.
except:
pass
with open('lineno.txt', 'w+') as lf:
for n, line in enumerate(lines):
# Do your processing here.
lf.seek(0) # go to beginning of lf
lf.write(str(n+skip)+'\n') # write the line number
lf.flush()
os.fsync() # flush and fsync make sure the lf file is written.