3

我有一个 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 万个数字,这可能需要一段时间。我找到了一个 truncate 的例子,但它没有用。

是否有任何类似于 python 的 array_shift (PHP) 的命令可以处理文本文件。

4

3 回答 3

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 并尝试从中读取一个数字。该数字是在上一次尝试期间处理的行数。然后它只是跳过所需的行数。

于 2012-10-01T18:01:59.920 回答
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.
于 2012-10-01T18:23:50.630 回答
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,它让这样的事情变得容易多了。

于 2012-10-01T18:10:10.793 回答