最近使用Python编写日志处理脚本时,对Python的几种读取文件的方式进行了实验。其中,linecache的行为引起了我的注意。

Python按行读取文件的经典方式有以下几种:

with open('blabla.log', 'r') as f:
for line in f.readlines():
## do something
with open('blabla.log', 'r') as f:
for line in f:
## do something
with open('blabla.log', 'r') as f:
while 1:
line = f.readline()
if not line:
break
## do something

以上几种方式都不支持对于文件按行随机访问。在这样的背景下,能够支持访直接访问某一行内容的linecache模块是一种很好的补充。

我们可以使用linecache模块的getline方法访问某一具体行的内容,官方文档中给出了如下用法:

>>> import linecache
>>> linecache.getline('/etc/passwd', 4)

在使用过程中我注意到,基于linecache的getline方法的日志分析会在跑满CPU资源之前首先占用大量内存空间,也就是在CPU使用率仍然很低的情况下,内存空间就会被迅速地消耗。

这一现象引起了我的兴趣。我猜测linecache在随机读取文件时,是首先依序将文件读入内存,之后寻找所要定位的行是否在内存当中。若不在,则进行相应的替换行为,直至寻找到所对应的行,再将其返回。

对linecache代码的阅读证实了这一想法。

在linecache.py中,我们可以看到getline的定义为:

def getline(filename, lineno, module_globals=None):
lines = getlines(filename, module_globals)
if 1 <= lineno <= len(lines):
return lines[lineno-1]
else:
return ''

不难看出,getline方法通过getlines得到了文件行的List,以此来实现对于文件行的随机读取。继续查看getlines的定义。

def getlines(filename, module_globals=None):
"""Get the lines for a file from the cache.
Update the cache if it doesn't contain an entry for this file already.""" if filename in cache:
return cache[filename][2]
else:
return updatecache(filename, module_globals)

由此可见,getlines方法会首先确认文件是否在缓存当中,如果在则返回该文件的行的List,否则执行updatecache方法,对缓存内容进行更新。因此,在程序启动阶段,linecache不得不首先占用内存对文件进行缓存,才能进行后续的读取操作。

而在updatecache方法中,我们可以看到一个有趣的事实是:

def updatecache(filename, module_globals=None):
"""Update a cache entry and return its list of lines.
If something's wrong, print a message, discard the cache entry,
and return an empty list.""" ## ... 省略... try:
fp = open(fullname, 'rU')
lines = fp.readlines()
fp.close()
except IOError, msg:
## print '*** Cannot open', fullname, ':', msg
return []
if lines and not lines[-1].endswith('\n'):
lines[-1] += '\n'
size, mtime = stat.st_size, stat.st_mtime
cache[filename] = size, mtime, lines, fullname
return lines

也就是说,linecache依然借助了文件对象的readlines方法。这也给了我们一个提示,当文件很大不适用readlines方法直接获取行的List进行读取解析时,linecache似乎也并不会成为一个很好的选择。

python linecache读取过程的更多相关文章

  1. python linecache模块读取文件的方法

    转自: python linecache模块读取文件 在Python中,有个好用的模块linecache,该模块允许从任何文件里得到任何的行,并且使用缓存进行优化,常见的情况是从单个文件读取多行. l ...

  2. Delphi中使用python脚本读取Excel数据

    Delphi中使用python脚本读取Excel数据2007-10-18 17:28:22标签:Delphi Excel python原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 . ...

  3. 【原创】控制perl和python脚本执行过程中脚本文件是否关闭的方法

    引子 跟踪perl和python脚本对文件的访问,实际过程中,perl和python解析器在解析完脚本后,直接关闭了 脚本文件,在进程中查询不到是访问文件的脚本文件名称. shell.perl和pyt ...

  4. python配置文件读取

    在代码实现的过程中,我们经常选择将一些固定的参数值写入到一个单独的配置文件中.在python中读取配置文件官方提供了configParser方法. 主要有如下方法(找官文):   (这家伙很懒,直接复 ...

  5. Linux环境下Python的安装过程

    Linux环境下Python的安装过程 前言 一般情况下,Linux都会预装 Python了,但是这个预装的Python版本一般都非常低,很多 Python的新特性都没有,必须重新安装新一点的版本,从 ...

  6. python下读取excel文件

    项目中要用到这个,所以记录一下. python下读取excel文件方法多种,用的是普通的xlrd插件,因为它各种版本的excel文件都可读. 首先在https://pypi.python.org/py ...

  7. Python逐块读取大文件行数的代码 - 为程序员服务

    Python逐块读取大文件行数的代码 - 为程序员服务 python数文件行数最简单的方法是使用enumerate方法,但是如果文件很大的话,这个方法就有点慢了,我们可以逐块的读取文件的内容,然后按块 ...

  8. python专题-读取xml文件

    关于python读取xml文章很多,但大多文章都是贴一个xml文件,然后再贴个处理文件的代码.这样并不利于初学者的学习,希望这篇文章可以更通俗易懂的教如何使用python 来读取xml 文件. 什么是 ...

  9. 【Netty源码分析】数据读取过程

    首先客户端连接到服务端时服务端会开启一个线程,不断的监听客户端的操作.

随机推荐

  1. Android(java)学习笔记31:泛型高级之通配符

    1. 泛型高级之通配符: package cn.itcast_07; import java.util.ArrayList; import java.util.Collection; /* * 泛型高 ...

  2. 【[AH2017/HNOI2017]礼物】

    题目 又是我不会做的题了 看看柿子吧 \[\sum(a_i+c-b_i)^2\] 最小化这个柿子 之所以不写下标是因为我们这个\(\{a\},\{b\}\)可以循环同构 那就开始化吧 \[\sum(a ...

  3. caffe实现focal loss层的一些理解和对实现一个layer层易犯错的地方的总结

    首先要在caffe.proto中的LayerParameter中增加一行optional FocalLossParameter focal_loss_param = 205;,然后再单独在caffe. ...

  4. vue常用事件

    一.事件监听 1. banner_edit.$watch('bannerForm.type', function () { //执行其他代码 console.log(666); this.banner ...

  5. PAT1064. Complete Binary Search Tree

    1064. Complete Binary Search Tree 题目大意 给定一个序列, 求其 生成Complete BST 的层序遍历. 思路 最开始把这个题想复杂了, 还想着建立结构体, 其实 ...

  6. JVM 监控以及内存分析

    1 内存分析1.1 jmap -histo 命令pid=`jps | awk '{if ($2 == "Jps") print $1}'`jmap -histo $pid > ...

  7. SuperSocket 学习

    http://www.cnblogs.com/Anaren/p/6382841.html https://www.assetstore.unity3d.com/en/#!/content/21721 ...

  8. android(eclipse)广播机制知识梳理(三)

    1:分类:   标准广播:没有先后顺序,无法被截断   有序广播:又先后顺序,可以截断 2:接收广播:首先进行注册,注册的方式有静态注册和动态注册.也就是在代码中注册和在AndroidManifest ...

  9. 课时90.div和span(掌握)

    为什么在这里讲解div和span呢,而不在html中讲解呢? 因为在我们的开发中div和span一般是配合css来使用的,来完成一定的效果,来设置一些属性,在前面我们没有学习css,所以体会不到它的效 ...

  10. git使用简介(二)

    附上廖雪峰老师Git教程https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 远程仓库 ...