最近使用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. 开始学习git

    今天看着廖雪峰的git使用教程开始学习git.不过没有将项目托管在github上,而是选择托管在了码云上. 看着明白做起来还是出了些问题,不过好在最后都解决了.果然眼高手低要不得. 试着将自己平时学习 ...

  2. Java Android 32位16位 MD5加密

    // md5加密 32位小写 private String Md5(String sourceStr) { String result = ""; try { MessageDig ...

  3. BZOJ3531:[SDOI2014]旅行(树链剖分)

    Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰 ...

  4. gluon实现softmax分类FashionMNIST

    from mxnet import gluon,init from mxnet.gluon import loss as gloss,nn from mxnet.gluon import data a ...

  5. hyper-net、ion、skip connection、fpn

    resnet的skip connection用的也是eltwise相加 fpn的浅层和高层融合用的eltwise相加 hyper-net和ion都是使用的concat的方式 hyper-net网络结构 ...

  6. Webstorm 添加新建.vue文件功能并支持高亮vue语法和es6语法

    添加新建.vue文件功能 ①Webstorm 右上角File-Plugins 搜索vue如果没有就去下载 点击serch in repositories ②点击安装vue.js ③安装成功后点击右下角 ...

  7. servlet 与 tomcat版本不匹配的问题

    严重: Failed to process JAR found at URL [/StudentLeave] for ServletContainerInitializers for context ...

  8. dijkstra 最小费用最大流

    前言:众所周知:spfa他死了 滑稽 dijkstra同样为最短路算法,为什么不能跑费用流qwq 好像是因为有负权边的缘故 但是如果我们如果使用某种玄学的将边权都拉回到正数的话 就可以跑了dijkst ...

  9. Android学习笔记_14_对JSON格式数据的处理

    public class ParseJsonTest extends AndroidTestCase{ public void testJson() throws Exception { String ...

  10. 写到 HTML 文档

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...