这个问题已经被问到了here和here,但没有一个解决方案对我有效
在Python 3中,如何有效地从大文件中删除第一行
我正在编写一个需要日志记录的程序,日志文件有一个可配置的最大大小,可以是无限的。因此,我不想使用readlines()
或类似的方法,因为这些方法会占用大量内存。速度不是一个大问题,但是如果不重写整个文件,也不需要临时文件,就可以完成,那就太好了
解决方案需要跨平台
示例日志文件:
[09:14:56 07/04/17] [INFO] foo
[23:45:01 07/04/17] [WARN] bar
[13:45:28 08/04/17] [INFO] foobar
... many thousands more lines
输出:
[23:45:01 07/04/17] [WARN] bar
[13:45:28 08/04/17] [INFO] foobar
... many thousands more lines
此代码将在循环中运行:
while os.path.getsize(LOGFILE) > MAXLOGSIZE:
# remove first line of file
以下解决方案均不起作用且内存效率低:
解决方案#1-有效但效率低下
with open('file.txt', 'r') as fin:
data = fin.read().splitlines(True)
with open('file.txt', 'w') as fout:
fout.writelines(data[1:])
解决方案#2-不起作用,将文件留空
import shutil
source_file = open('file.txt', 'r')
source_file.readline()
target_file = open('file.txt', 'w')
shutil.copyfileobj(source_file, target_file)
解决方案#3-有效,但使用额外的文件:
with open("file.txt",'r') as f:
with open("new_file.txt",'w') as f1:
f.next() # skip header line
for line in f:
f1.write(line)
试试这个。它使用你提到的第三种方法,但不会生成新文件
因此,这种方法非常粗糙。如果您的线条尺寸大致相同,且标准偏差较小,则效果良好。我们的想法是将文件的一部分读入一个缓冲区,该缓冲区足够小,可以节省内存,但足够大,这样两端的书写形式就不会把事情弄糟(因为行的大小大致相同,差异很小,我们可以交叉手指祈祷它能工作)。我们基本上会跟踪我们在文件中的位置并来回跳转。我使用
collections.deque
作为缓冲区,因为它从两端都具有良好的append
性能,并且我们可以利用队列的FIFO特性:现在,让我们用一个运行良好的假装文件来尝试这一点:
最后:
如果
dropfirst
<buffersize
有点“松懈”。因为您只想删除第一行,所以只需保留dropfirst=1
,您可以制作buffersize=100
或是为了安全起见。它将比阅读“成千上万行”更节省内存,如果没有一行比前几行大,那么您应该是安全的。但请注意,这是非常粗糙的边缘相关问题 更多 >
编程相关推荐