python 文件处理汇总

来源:互联网 发布:姚明每个赛季数据 编辑:程序博客网 时间:2024/05/18 00:34

题外话:不能做到汇总所有的,尽可能汇总下。
刚开始碰到的日志文件大概300,400M左右,一次性读取可行的,后来碰到了7,8G大小的日志文件,总不能处理时,每次都切割他们吧。我的内存也就只有4G的配置。所以想像大牛们那样处理比较大点的文件。所以开始学习下大牛们的处理方式。

1.迭代器
2.生成器
3.文件打开方式
4.文件读
5.文件写
6.文件关闭

博文部分来源:http://www.cnblogs.com/kaituorensheng/p/3826911.html#_label1

1)先说迭代器:

    迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,知道所有的元素被访问完结束。迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退。
   迭代器有两个基本的方法

next方法:返回迭代器的下一个元素__iter__方法:返回迭代器对象本身

示例1)文件迭代器 :

#当使用open()带打开一个文件时,这是就生成一个文件迭代器。#可以迭代的不一定是迭代器,比如说列表,字符串呀,但是迭代器一定可以迭代。>>>f.open()>>>f = open("E:\python_test\831\file.log", 'r')>>>f.readline()'hello there line  1'>>>f.readline()'hello there line  2'>>>f.readline()'hello there line  3'#readline就是这样一行一行的处理文件,把读的行,放到内存中的。#既然是迭代器,当然可以使用next()了。>>>f.next()'hello there line 4\n'>>>f.next()'hello there line 5\n'#注意的有两点 #   1)next和readline的输出有点不同,带上换行符。#   2)不能使用next和readline交叉使用,会直接报错。

示例2)列表包装成迭代器:

#都知道列表等可迭代对象,但不是迭代器,那么使用一个函数可以将他们包装为迭代对象。#使用iter()函数进行迭代器的转换>>>ls = [1,2,3,4,5]>>>ls.next()#直接报错>>>print  ls[1,2,3,4,5]>>>it = iter(ls)  #或者使用it = ls.__iter__()也是一样的>>>print it<listiterator object at 0x000000000454E0F0>#能看出来,打印的出来的东西就不一样。>>>it.next()1>>>it.next()2>>>it.next()3#可以看见it具有了迭代器的属性。#使用  isinstance(ls,iterable)  判断对象是否可以迭代#使用  isinstance(it,iterator) 判断对象是否是迭代器。

示例3)查看源码,

>>> from collections import Iterator, Iterable>>> help(Iterator)Help on class Iterator:#帮助信息如下:class Iterator(Iterable) |  Method resolution order: |      Iterator |      Iterable |      builtins.object    |#注解:从这里可以看出Iterable继承自object, Iterator继承自Iterable。 |  Methods defined here: | |  __iter__(self) | |  __next__(self) |      Return the next item from the iterator. When exhausted, raise StopIteration......>>> help(Iterable)Help on class Iterable:class Iterable(builtins.object) |  Methods defined here: | |  __iter__(self)......

示例4)使用copy模块的deepcopy复制迭代器。

>>> import copy>>> I=iter(L)>>> J=copy.deepcopy(I)>>> next(I)1>>> next(I)2>>> next(J)1#出现,报错,这示例4是网上copy下来的。有空理理。

示例5)关于查看一个变量占用的内存空间—》
—》为了查看读取文件后,保存文件数据的那个list占用的内存空间。
当然,在python中变量只是类似c语言中指向那个内存空间的指针而已,准确的说那个对象占用的空间。

>>>import sys>>>f = open("E:\python_test\831\file.log")>>>t = f.readlines()>>>len(t)251565  #列表的长度,也就是说文件中总共有这么多行。>>>getsizeof(t)2115952  #这是以字节为单位的。#这个地方有个问题,我的源文件是100M大小。还有就是getsizeof(t)的大小显示只有2M.#但是len(t)的确有25w多行。list有25w多个元素。是不是哪里出问题了

我就换了方法:

#就是统计前100个元素的对象的总占用内存空间,再乘上倍数。#也就是说 size = 100个元素占用的内存的总大小。#总占用就是 all = size * 250000/100>>>import sys>>>f = open("E:\python_test\831\file.log")>>>t = f.readlines()>>>size = 0>>> for x in range(0,101):...     size += sys.getsizeof(t[x])>>>size46098  #这是以字节为单位的。>>>all = size *250000/100115245000  #109M左右,因为是估算的,所以基本正确。我那文件100M左右。

到这里,我想可能是sys.getsizeof()统计该列表中的数据是有问题的。那么用什么来统计呢。我在想是不是getsizeof()还有什么参数要传递,看了下,没发现。

示例6)使用psutil模块获取内存.
这是看到别人博客的,可以去参考下:
http://www.mamicode.com/info-detail-1343554.html

#coding:utf-8import psutilimport sysimport  osps = psutil.Process(os.getpid())first = ps.memory_full_info().rssprint "开始的占用:",firstf = open("E:\python_test\831\core-trace-2017-08-31-07.log.1", 'r')t =  f.readlines()f.close()end = ps.memory_full_info().rssprint "最后占用:",endprint "差值:", end-first输出如下:开始的占用: 12435456  #这里就只有11M最后占用: 134447104差值: 122011648 #116M这其中包括其他的加载进来的数据占用,包括其他对象占用的空间。

2)生成器:

生成器是支持迭代协议的对象:他们也有next方法,其特征是不是一次性放回所以值,而是每次输出一个元素,通过yield语句来进行一次次状态保存,以便后续继续调用能接续上。

示例1)列表和生成器

#列表和生成器.不同之处就是一个【】,一个()。且返回对象不同。>>> L = [x for x in range(5)]>>> L[0, 1, 2, 3, 4]>>> S = (y for y in range(5))>>> S<generator object <genexpr> at 0x00000000026527E0>>>> S.next()  #生成器可以使用next方法,但列表等可迭代的就不行。0>>> S.next()1>>> S.next()2#注意一点的是到没有数据时,会引发一个StopIteration的异常。

示例2)生成器函数

def  g(N):   for  i in range(N):         yield i**2for i in g(5):    print i,':',输出如下:0 : 1 : 4 : 9 : 16 :

示例3)生成器函数协议:send和next
下面的例子来自别人的博客:可以跳过去看看:
http://blog.chinaunix.net/uid-11989741-id-3389226.html

#next就不讲了,说说send#生成器.send的值是yield表达式返回的,所以要yield执行后才可以使用send.def countdown(n):    print "Counting down from", n    while n >= 0:        newvalue = (yield n)        # If a new value got sent in, reset n with it        if newvalue is not None:            n = newvalue        else:            n -= 1# The holy grail countdownc = countdown(5)for x in c:    print x    if x == 5:        c.send(3)输出如下:Counting down from 55210

send的作用就是给yield语句另一个值。
关于send是这样说的 send给generator的value会成为当前yield的结果 并且
send的返回结果是下一个yield的结果(或者引发StopIteration异常)也就是说此处s.send(3)会返回3 并且在第8行 suspend for循环 调用generator的next函数 从第9行开始执行 此时当前yield的值为None 所以n -= 1 之后yield2 并且suspend在第8行

+++++++++++++++++++++++++++++++++++++
+讲了这么多和文件无关的操作。下面就开始文件处理汇总。+
+++++++++++++++++++++++++++++++++++++
文件操作:可以跳转下面去看看,很全,很强大:
http://www.cnblogs.com/rollenholt/archive/2012/04/23/2466179.html

3)文件的打开方式: open( )

open()和file()的关系:转载至如下博客,自行跳转到:
http://www.cnblogs.com/allenblogs/archive/2010/09/13/1824842.html

file(name[, mode[, buffering]])
file()函数用于创建一个file对象,它有一个别名叫open(),可能更形象一些,它们是内置函数。来看看它的参数。它参数都是以字符串的形式传递的。name是文件的名字。
mode是打开的模式,可选的值为r w a U,分别代表读(默认) 写 添加支持各种换行符的模式。用w或a模式打开文件的话,如果文件不存在,那么就自动创建。此外,用w模式打开一个已经存在的文件时,原有文件的内容会被清空,因为一开始文件的操作的标记是在文件的开头的,这时候进行写操作,无疑会把原有的内容给抹掉。由于历史的原因,换行符在不同的系统中有不同模式,比如在 unix中是一个\n,而在windows中是‘\r\n’,用U模式打开文件,就是支持所有的换行模式,也就说‘\r’ ‘\n’ ‘\r\n’都可表示换行,会有一个tuple用来存贮这个文件中用到过的换行符。不过,虽说换行有多种模式,读到python中统一用\n代替。在模式字符的后面,还可以加上+ b t这两种标识,分别表示可以对文件同时进行读写操作和用二进制模式、文本模式(默认)打开文件。
buffering如果为0表示不进行缓冲;如果为1表示进行“行缓冲“;如果是一个大于1的数表示缓冲区的大小,应该是以字节为单位的。

file对象有自己的属性和方法。先来看看file的属性。closed #标记文件是否已经关闭,由close()改写 encoding #文件编码 mode #打开模式 name #文件名 newlines #文件中用到的换行模式,是一个tuple softspace #boolean型,一般为0,据说用于print

open()或file()

文件操作:fp = open("test.txt",'w')     直接打开一个文件,如果文件不存在则创建文件关于open 模式:w      以写方式打开,a      以追加模式打开 (从 EOF 开始, 必要时创建新文件)r+     以读写模式打开w+     以读写模式打开 (参见 w )a+     以读写模式打开 (参见 a )rb     以二进制读模式打开wb     以二进制写模式打开 (参见 w )ab     以二进制追加模式打开 (参见 a )rb+    以二进制读写模式打开 (参见 r+ )wb+    以二进制读写模式打开 (参见 w+ )ab+    以二进制读写模式打开 (参见 a+ )

示例1)

#在ipython中:In [17]: f = open("hexian.txt",'a+')In [18]: f.readlines()Out[18]: ['hexian 1\n', 'hexian 2\n', 'hexian 3']

本文文件内容是:

hexian 1hexian 2hexian 3

4)文件的读 :read,readline ,readlines

这里需要注意的一点是:文件指针,在调用任意一个读操作,都会随之变动,直到指针指向末尾。此时再去读操作,就返回为空字符串。

fp.read([size])       #size为读取的长度,以byte为单位fp.readline([size])   #读一行,如果定义了size,有可能返回的只是一行的一部分fp.readlines([size])  #把文件每一行作为一个list的一个成员,并返回这个list。#其实它的内部是通过循环调用readline()来实现的。#如果提供size参数,size是表示读取内容的总长,也就是说可能只读到文件的一部分。list(fp):效果和fp.readlines()一样In [43]: list(f)Out[43]: ['hexian 1\n', 'hexian 2\n', 'hexian 3\n']

这里说下read(size) :size 字符个数
这里写图片描述
那么就要提到seek
先说tell():tell是告诉我们当前指向的位置的。

fp.tell()

  f.tell()   #返回文件操作标记的当前位置,以文件的开头为原点


fp.seek(offset[,whence])

将文件打操作标记移到offset的位置。这个offset一般是相对于文件的开头来计算的,一般为正数。
但如果提供了whence参数就不一定了。
whence可以为
0表示从头开始计算
1表示以当前位置为原点计算。
2表示以文件末尾为原点进行计算。
注意:如果文件以a或a+的模式打开,每次进行写操作时,文件操作标记会自动返回到文件末尾。

《图1》
这里写图片描述
我加个空行再试试:
这里写图片描述

没有返回值。如下。还有更改文件指针的位置。

In [79]: print f.seek(0)NoneIn [80]: f.readline()Out[80]: 'hexian 1\n'

还可以使用负数:

>>> f.seek(-3, 2) # Go to the 3rd byte before the end#就是说从2(文件末尾),倒着数上个字符。

这里写图片描述

需要注意的是,如果该文件被打开或者使用’a’或’A+’追加,那么写的时候,文件指针就指向了文件末尾了。
如果该文件只打开使用“a”的追加模式写,这种方法本质上是一个空操作,但读使能(模式’a+’),它仍然在追加模式打开的文件非常有用。


f.next() 操作

fp.next()      #返回下一行,并将文件操作标记位移到下一行.

之前提到的迭代器的next方法,就是这个,一个文件对象,是一个迭代器对象。
注意,文件对完了,再次next,会引起一个迭代器都有的异常:StopIteration

fp.truncate([size])
把文件裁成规定的大小,默认的是裁到当前文件操作标记的位置。如果size比文件的大小还要大,依据系统的不同可能是不改变文件,也可能是用0把文件补到相应的大小,也可能是以一些随机的内容加上去。

5)文件写操作

fp.write(str)
#把str写到文件中,write()并不会在str后加上一个换行符

In [79]: f = open('hexian.txt','w+')In [80]: f.tell()Out[80]: 0L#可以看出来,如果不是a+的话,w+是指向开头的,如果这时候去写的话,就会覆盖文件。

这里使用a+的尝试,发现个问题:
这里写图片描述
tell显示的还是0L,但是写的时候发现是追加。那么大概是这样的:a+是追加,并且可读模式。所以的确文件指针是指向开头的,但是写的时候做了处理,是指针指向文件末尾。写完,重新返回刚才读的位置。

fp.writelines(seq)
#把seq的内容全部写到文件中(多行一次性写入)。这个函数也只是忠实地写入,不会在每行后面加上任何东西。

这里写图片描述
这里写图片描述

6)文件的关闭:

f.close()
现在比较好用的是使用with语句打开关闭文件,不用自己使用try语句捕捉文件打开异常。

In [116]: with open('hexian.txt','r') as f:     ...:      print   f.readlines() #在with区域块里面做操作     ...:      #一旦退出with块,就关闭文件了。     ...:In [120]: f.seek(0)-----------------------------------------------------------------ValueError                         Traceback (most recent call last)<ipython-input-120-d0cb2b3c0dfb> in <module>()----> 1 f.seek(0)ValueError: I/O operation on closed file

直接报错。
和文件操作有关的一个python自带的模块,csv模块,我经常用到。
以后有空再 补充。写csv去。

原创粉丝点击