2012-10-01 64 views
3

我有一个包含数字列表(每行1个数字)的22mb文本文件。我试图让python读取数字,处理数字并将结果写入另一个文件。所有这些工作,但如果我必须停止该计划,它从头开始从头开始。起初我尝试使用mysql数据库,但速度太慢。我以这种方式处理的数字是约4倍。我希望能够在处理号码后删除该行。您可以在每次重新启动时看到它必须搜索硬盘驱动器的文件名以确保它到达停止的位置。有了150万的数字,这可能需要一段时间。我发现一个截断的例子,但它没有工作。从文件中读取行,处理它,然后将其删除

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

+0

数字是否是唯一的? – kalgasnik

+0

您是否正在尝试将每个数字写入单独的文件?如果是这样,为什 – root

+0

你可以尝试使用Postgres和pl/pgsql来执行数据库本身的任何计算...... – moooeeeep

回答

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,很好的答案 - 你可以利用[enumerate](http://docs.python.org/library/functions.html#enumerate)删除'i + = 1'部分。 – girasquid

+0

值得检查一下用例是什么在中间停止的地方。在每一行上写文件最终会成为你花费大部分时间的地方。如果没有中途停止的情况,最好是明确地说明这些情况,而不是做数千次不必要的文件写入。如果你的程序只是随机死亡,那么每100或1000行写一次也许会更好。 – BostonJohn

+1

也许我错过了一些东西,但是这个解决方案不会跳过第一行吗?在第一次通过循环时,我们迭代i以使它大于0 - 所以实际上读取的第一行是第一行,而不是第0行不是它? – sager89

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您还可以使用搁置模块,确保你与所述写回= False选项打开它。尽管我真的推荐Redis,但它让这样的事情变得更加容易。

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. 
相关问题