第十二章 Python文件操作

发布时间:2019-09-14 09:45:54编辑:auto阅读(1743)

    12.1 open()

    open()函数作用是打开文件,返回一个文件对象。

    用法格式:open(name[, mode[, buffering[,encoding]]]) -> file object

    name 文件名

    mode 模式,比如以只读方式打开

    buffering 缓冲区

    encoding 返回数据采用的什么编码,一般utf8或gbk

    Mode

    Description

    r只读,默认
    w只写,打开前清空文件内容
    a追加
    a+读写,写到文件末尾
    w+可读写,清空文件内容
    r+可读写,能写到文件任何位置
    rb二进制模式读
    wb二进制模式写,清空文件内容

    例如:打开一个文件

    >>> f = open('test.txt', 'r')
    >>> f.
    f.__class__(         f.__new__(           f.encoding           f.readinto(
    f.__delattr__(       f.__reduce__(        f.errors             f.readline(
    f.__doc__            f.__reduce_ex__(     f.fileno(            f.readlines(
    f.__enter__(         f.__repr__(          f.flush(             f.seek(
    f.__exit__(          f.__setattr__(       f.isatty(            f.softspace
    f.__format__(        f.__sizeof__(        f.mode               f.tell(
    f.__getattribute__(  f.__str__(           f.name               f.truncate(
    f.__hash__(          f.__subclasshook__(  f.newlines           f.write(
    f.__init__(          f.close(             f.next(              f.writelines(
    f.__iter__(          f.closed             f.read(              f.xreadlines(

    open()函数打开文件返回一个文件对象,并赋予遍历f,f就拥有了这个文件对象的操作方法。

    方法

    描述

    f.read([size])读取size字节,当未指定或给负值时,读取剩余所有的字节,作为字符串返回
    f.readline([size])从文件中读取下一行,作为字符串返回。如果指定size则返回size字节
    f.readlines([size])读取size字节,当未指定或给负值时,读取剩余所有的字节,作为列表返回
    f.write(str)写字符串到文件
    f.writelines(seq)写序列到文件,seq必须是一个可迭代对象,而且要是一个字符串序列
    f.seek(offset[, whence=0])在文件中移动文件指针,从whence(0代表文件起始位置,默认。1代表当前位置。2代表文件末尾)偏移offset个字节
    f.tell()返回当前在文件中的位置
    f.close()
    关闭文件
    f.flush刷新缓冲区到磁盘

    12.2 文件对象操作

    写一个测试文件test.txt举例:

    # cat test.txt
    1.Python
    2.Java
    3.C++
    4.Ruby

    12.2.1 read()读取所有内容

    >>> f = open('test.txt', 'r')
    >>> f.read()
    '1.Python\n2.Java\n3.C++\n4.Ruby\n'

    指定读取多少字节:

    >>> f = open('test.txt', 'r')
    >>> f.read(9)  # 获取指定字节
    '1.Python\n'

    12.2.2 readline()读取下一行内容

    >>> f = open('test.txt', 'r')
    >>> f.readline()
    '1.Python\n'
    >>> f.readline()
    '2.Java\n'

    12.2.3 readlines()读取所有内容返回一个列表

    >>> f = open('test.txt', 'r')
    >>> f.readlines()
    ['1.Python\n', '2.Java\n', '3.C++\n', '4.Ruby\n']

    12.2.4 wirte()写入字符串到文件

    >>> f = open('test.txt', 'a')  # 以追加方式打开文件
    >>> f.write("5.Shell\n")  # 这一步并没有真正写到文件
    >>> f.flush()  # 刷新到磁盘才写到文件
    # cat test.txt
    1.Python
    2.Java
    3.C++
    4.Ruby
    5.Shell

    12.2.5 wirtelines()写入一个序列字符串到文件

    >>> f = open('test.txt', 'a')
    >>> f.writelines(['a','b','c'])
    >>> f.flush()
    # cat test.txt
    1.Python
    2.Java
    3.C++
    4.Ruby
    5.Shell
    abc

    12.2.6 seek()从指定位置读取

    >>> f = open('test.txt', 'r')
    >>> f.tell()
    0
    >>> f.seek(9)
    >>> f.tell()
    9
    >>> f.seek(5,1)  # 1表示从当前位置开始
    >>> f.tell()
    14

    12.2.7 tell()返回当前指针位置

    >>> f = open('test.txt', 'r')
    >>> f.tell()
    0
    >>> f.readline()
    '1.Python\n'
    >>> f.tell()   
    9
    >>> f.readline()
    '2.Java\n'
    >>> f.tell()   
    16
    >>> f.close()  # 使用完后关闭文件


    博客地址:http://lizhenliang.blog.51cto.com

    QQ群:323779636(Shell/Python运维开发群


    12.3 文件对象增删改查

    在shell中,我们要想对文件指定行插入内容、替换等情况,使用sed工具很容易就实现。在本章节讲的open()函数并没有直接类似与sed工具的方法,要想实现这样的操作,变通的处理能到达此效果,主要思路是先读取内容修改,再写会文件,以下举几个常用的情况

    12.3.1 在第一行增加一行

    例如:在开头添加一个test字符串

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    f = open('test.txt', 'r')
    data = f.read()
    data = "test\n" + data
    f = open('test.txt', 'w')
    f.write(data)
    f.flush()
    f.close()
    
    # python test.py
    # cat test.txt
    test
    1.Python
    2.Java
    3.C++
    4.Ruby

    先将数据读出来,然后把要添加的test字符串拼接到原有的数据,然后在写入这个文件。

    12.3.2 在指定行添加一行

    例如:在第二行添加一个test字符串

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    f = open('test.txt', 'r')
    data_list = f.readlines()  # 经测试,此方法比下面迭代效率高
    # data_list = []
    # for line in f:
    #     data_list.append(line)
    data_list.insert(1, 'test\n')
    # data = ''.join(data)
    f = open('test.txt', 'w')
    # f.write(data)
    f.writelines(data_list)  
    f.flush()
    f.close
    
    # python test.py
    # cat test.txt
    1.Python
    test
    2.Java
    3.C++
    4.Ruby

    先将数据以列表存储,就可以根据下标插入到指定位置,也就是哪一行了。再通过join把列表拼接成字符串,最后写到文件。

    12.3.3 在匹配行前一行或后一行添加test字符串

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    f = open('test.txt', 'r')
    data_list = f.readlines()
    data_list.insert(2-1, 'test\n')  # 在指定行减去一行就是上一行了,下一行插入同理
    f = open('test.txt', 'w')
    f.writelines(data_list)
    f.flush()
    f.close

    12.3.4 删除指定行

    例如:删除第三行,与在指定行添加同理

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    f = open('test.txt', 'r')
    data_list = f.readlines()
    data_list.pop(2)
    f = open('test.txt', 'w')
    f.writelines(data_list)
    f.flush()
    f.close

    例如:只保留第一行至第三行

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    f = open('test.txt', 'r')
    data_list = f.readlines()[0:2]  # 列表切片
    f = open('test.txt', 'w')
    f.write(data_list)
    f.flush()
    f.close

    12.3.5 删除匹配行

    例如:删除匹配Py字符的行

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    f = open('test.txt', 'r')
    data = f.readlines()
    # data_list = []
    # for line in data:
    #     if line.find('Py') == -1:   # 如果当前行不包含Py字符,会返回-1,否则返回下标
    #         data_list.append(line)
    data_list = [line for line in data if line.find('Py') == -1]  
    f = open('test.txt', 'w')
    f.writelines(data_list)
    f.flush()
    f.close

    12.3.6 全局替换字符串

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    f = open('test.txt', 'r')
    data = f.read()
    data.replace('old string', 'new string')
    f = open('test.txt', 'w')
    f.write(data)
    f.flush()
    f.close

    12.3.7 在指定行替换字符串

    例如:将C++改为C#

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    f = open('test.txt', 'r')
    data = f.readlines()
    data_list = []
    for line in data:
        if data.index(line) == 2:
            data_list.append(line.replace('++', '#'))
        else:
            data_list.append(line)
    f = open('test.txt', 'w')
    f.writelines(data_list)
    f.flush()
    f.close

    12.3.8 处理大文件

    在读取上G文件时,直接读取所有内容会导致内存占用过多,内存爆掉。要想提高处理效率,有以下两种方法:

    方法1:open()打开文件返回的对象本身就是可迭代的,利用for循环迭代可提高处理性能

    >>> f = open('test.txt')
    >>> for line in f:
    ...   print line   # 每行后面会有一个换行符\n,所以会打印出来换行符,可以使用line.strip('\n')去除
    ...
    1.Python
    2.Java
    3.C++
    4.Ruby

    方法2:每次只读取固定字节

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    f = open('test.txt')
    while True:
        data = f.read(1024)  # 每次只读取1024字节
        if not data: break

    12.3.9 下载文件

    方法1:
    import urllib
    url = "http://nginx.org/download/nginx-1.10.1.tar.gz"
    urllib.urlretrieve(url, "nginx-1.10.1.tar.gz")
    
    方法2:
    import urllib2
    url = "http://nginx.org/download/nginx-1.10.1.tar.gz"
    f = urllib2.urlopen(url).read()
    with open("nginx-1.10.1.tar.gz", "wb") as data:
        data.write(f)

    12.4 fileinput

    fileinput模块是Python内建模块,用于遍历文件,可对多文件操作。

    方法

    描述

    fileinput.input([files[, inplace[, backup[, mode[, openhook]]]]])

    files:文件路径,多文件这样写['1.txt,'2.txt'']

    inplace:是否将标准输出写到原文件,默认是0,不写

    backup:备份文件扩展名,比如.bak

    mode:读写模式,默认r,只读

    openhook:

    fileinput.isfirstline()检查当前行是否是文件的第一行
    fileinput.lineno()返回当前已经读取行的数量
    fileinput.fileno()返回当前文件数量
    fileinput.filelineno()返回当前读取行的行号
    fileinput.filename()返回当前文件名

    12.4.1 遍历文件内容

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import fileinput
    for line in fileinput.input('test.txt'):
        print line
        
    # python test.py 
    1.Python
    2.Java
    3.C++
    4.Ruby

    12.4.2 返回当前读取行的行号

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import fileinput
    for line in fileinput.input('test.txt'):
        print fileinput.filelineno()
        print line,  # 逗号忽略换行符
        
    # python test.py
    1
    1.Python
    2
    2.Java
    3
    3.C++
    4
    4.Ruby

    12.4.3 全局替换字符,修改原文件

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import fileinput
    for line in fileinput.input('test.txt', backup='.bak', inplace=1):
        line = line.replace('++','#')
        print line,

    先把要操作的文件备份一个以.bak的后缀文件,inplace=1是将标准输出写到原文件,也就是这个脚本如果没有标准输出,就会以空数据写到原文件。

    12.4.4 对多文件操作

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import fileinput
    for line in fileinput.input(['test.txt', 'test2.txt']):
        print line,
    12.4.5 实时读取文件新增内容,类似tail -f
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    with open('access.log') as f:
         f.seek(0,2)   # 每次打开文件都将文件指针移动到末尾
         while True:  
             line = f.readline()
             if line:
                 print line,

    这个死循环会一直执行下面的操作。很消耗性能。

    我们可以加个休眠,每秒读取一次:

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import time
    with open('access.log') as f:
         f.seek(0,2)
         while True:
             line = f.readline()
             if line:
                 print line,
             else:
                 time.sleep(1)

    12.5 shutil

    shutil模块是Python内建模块,用于文件或目录拷贝,归档。

    方法

    描述

    shutil.copyfile(src, dst)复制文件
    shutil.copytree(src, dst)复制文件或目录
    shutil.move(src, dst)移动文件或目录
    shutil.rmtree(path,ignore_errors=False, onerror=None)递归删除目录。os.rmdir()不能删除有文件的目录,就可以用这个了
    shutil.make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, dry_run=0, owner=None, group=None, logger=None)

    Python2.7以后才有这个方法。

    功能是创建zip或tar归档文件。

    base_name:要创建归档文件名

    format:归档文件格式,有zip、tar、bztar、gztar

    root_dir:要压缩的目录

    base_dir:?

    用法:shutil.make_archive('wp','zip','/root/wordpress')   

    12.6 with语句

    在处理一些事务时,可能会出现异常和后续的清理工作,比如读取失败,关闭文件等。这就用到了异常处理语句try...except,如下:

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    f = open('test.txt')
    try:
        data = f.read()
    finally:
        f.close()

    Python对于这种情况提供了一种更简单的处理方式,with语句。处理一个文件时,先获取一个文件句柄,再从文件中读取数据,最后关闭文件句柄。如下:

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    with open('test.txt') as f:
        data = f.read()

    可见这种方式显得更简约,一些异常、清理工作都交给with处理了。


关键字