Python之文件操作

本文详细介绍了Python的文件操作,包括文件的打开、读写模式、文件指针操作,以及上下文管理。还深入讲解了io模块中的StringIO和BytesIO,用于内存中的文本和二进制数据操作。同时,文章涵盖了序列化和反序列化的概念,特别提到了pickle和Json库的使用,以及MessagePack的高效压缩特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:文件

文件I/O常用操作:

  1. open:打开或者要创建的文件名,如果不指定路径,默认是当前路径!

    mode模式:
    r:缺省的,表示只读打开
    w:只写打开,默认覆盖原文件
    x:创建并写入一个新文件,如果文件已经存在抛出异常
    a:写入打开,如果文件存在,则追加
    b:二进制模式
    t:缺省的,文本模式
    +:读写打开一个文件,给原来只读、只写方式打开提供缺省的读或写能力。

  2. read:读取

    read(size):size表示读取多个字符或字节;负数或者None表示读取到EOF

  3. write:写入

    write(s):把字符串写入到文件中并返回字符的个数
    writelines(lines):将字符串列表写入文件

  4. close:关闭

    1,flush并关闭文件对象
    2,文件已经关闭,再次关闭没有任何效果

  5. readline:读取行

    readline(size):一行一行读取文件内容,size设置一次能读取行内几个字符或字节

  6. readlines:多行读取

    readlines(hint):读取所有行的列表,指定hint则返回指定的行数

  7. seek:文件指针操作

  8. tell:指针位置

  9. errors:None和strict表示有编码错误将抛出ValueError异常;ignore表示忽略

  10. newline:文本模式中,换行的转换。可以为None、”、’\r’、’\n’、’\r\n’

    读时:None表示’\r’,’\n’,’\r\n’都被转换为’\n’;表示不会自动转换通用换行符;其他合法字符表示换行就是指定字符,就会按照指定字符分行

    写时:None表示’\n’都会被替换为系统缺省行分隔符os.linesep;’\n’或”表示不替换;其他合法字符表示’\n’会被替换为指定的字符

  11. closed:关闭文件描述符

    True:表示关闭
    False:会在文件关闭后保持这个描述符

  12. seekable():是否可seek

  13. readable():是否可读

  14. writable():是否可写

  15. closed:是否已经关闭

    打开操作:打开一个文件,返回一个文件对象(流对象)和文件描述符。打开文件失败,则返回异常。
    格式:
    open(file, mode=’r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

    文件模式:不同模式下,操作函数不相同,表现的结果也不一样。
        文本模式:
            文本模式支持从开头向后偏移的方式:
            1,whence为1表示从当前位置开始偏移,但是只支持偏移0,相当于原地不动
            2,whence为2表示从EOF开始,只支持偏移0,相当于移动文件指针到EOF
            3,seek是按字节偏移的
        二进制模式:
            1,whence为0时,表示从头开始,offset只能是正整数
            2,whence为1时,表示当前位置,offset可正可负
            3,whence为2时,表示从EOF开始,offset可正可负
    

文件指针:指向当前(字节)位置!!!

  1. tell():显示指针当前位置
  2. seek(cookie, whence=0):移动指针位置。

cookie偏移量
whence:从哪里开始:

  • 0:缺省,表示从头开始,offset只能是正整数
  • 1:表示从当前位置,offset只接受0
  • 2:表示从EOF开始,offset只接受0

BUFFERING:缓冲区

  • -1:表示使用缺省大小的buffer,如果是二进制模式,使用io.DEFAULT_BUFFER_SIZE,默认是4096或者是8192。
  • 0:只在二进制模式使用,表示关闭buffer
  • 1:只在文本模式使用,表示使用行缓冲,意思是见到换行符就flush
  • >1:大于1用于指定buffer的大小

buffer缓冲区:

  • 缓冲区指一个内存空间,一般来说是一个FIFO队列,到缓冲区满或者达到阈值,数据才会flush到磁盘!
  • flush():将缓存区数据写入磁盘
  • close():关闭前会调用flush()

重点:

  1. 文本模式,一般都用默认缓冲区大小
  2. 二进制模式,是一个个字节的操作,可以指定buffer的大小
  3. 一般来说,默认缓冲区大小是个比较好的选择,除非明确知道,否则不调整它
  4. 一般编程中,明确知道需要写磁盘,都会手动调用依次flush,而不是等到自动flush或者close的时候!

二,文件I/O上下文管理

上下文管理:一种特殊的语法,交给解释器去释放文件对象
格式:

  • 使用with… as 关键字
  • 上下文管理的语句块并不会开启新的作用域
  • with语句块执行完的时候,会自动关闭文件对象

代码:

def copys(src:str, dst:str):
    with open(src) as srcfile:
        with open(dst, 'w') as dstfile:
            dstfile.write(srcfile.read())

三,io模块之StringIO、BytesIO

1. StringIO:io模块中的类

from io import StringIO

重点:一般来说,磁盘的操作比内存的操作要慢的多,内存足够的情况下,一般的优化思路是少落地(尽量不写入磁盘),减少磁盘IO的过程,可以大大提高程序的运行效率!

  • 内存中,开辟的一个文本模式的buffer,可以像文件对象一样操作它

  • 当close方法被调用的时候,这个buffer会被释放

StringIO操作:
getvalue():获取全部内容,跟文件指针没有关系!
代码:

    sio = StringIO()
    sio.write('hello word')
    sio.getvalue()
    sio.close()

1. BytesIO:io模块中的类

from io import BytesIO

  • 内存中,开辟的一个二进制模式的buffer,可以像文件对象一样操作它
  • 当close方法被调用的时候,这个buffer会被释放

BytesIO操作:
代码:

    from io import BytesIO
    bio = BytesIO()
    bio.write(b'hello word')
    bio.getvalue()
    bio.close()

1. file-like对象

  • 类文件对象,可以像文件对象一样操作
  • socket对象、输入输出对象(stdin、stdout)都是类文件对象!

代码:

    from sys import stdout
    f1 = stdout
    print(type(f1))
    f1.write('hello word')

四,路径操作

os模块:
3.4版本之前:

from os import path
代码:linux下执行

p = path.join('/etc', 'sysconfig', 'network')
print(type(p), p) # <class 'str'> /etc/sysconfig/network
print(path.exists(p)) # True
print(path.split(p)) # ('/etc/sysconfig', 'network')
print(path.abspath('.')) # 返回当前绝对路径
print(path.dirname(p)) # 返回除文件的路径,/etc/sysconfig
print(path.basename(p)) # 返回路径的文件名,network
windows:
f = path.abspath('')
print(path.splitdrive(f)) # ('C:', '\\Users\\aironm')
linux:
print(path.splitdrive(p)) # ('', '/etc/sysconfig/network')
3.4版本之后:
    pathlib模块:
    from pathlib import Path

    目录操作:
    1,路径
        代码:
        from pathlib import Path

        dir1 = Path() # 创建一个dir1对象
        dir1 = Path('etc', 'sysconfig', 'network/srcitpts')
        print(dir1)
    路径拼接和分解:
        拼接:
            操作符:/
                格式:
                    Path对象 / Path对象
                    Path对象 / 字符串或者字符串 / Path对象
                代码:
                file2 = Path()
                file3 = file2 / 'test.xml'
                file3 # PosixPath('test.xml')
                file3.resolve() # PosixPath('/home/python/Process/Python364/Test2/test.xml')


        分解:
            parts:属性,可以返回路径中的每一个部分
                代码:
                file1 = Path('.')
                file1.absolute() # PosixPath('/home/python/Process/Python364/Test2')
                file1.absolute().parts # ('/', 'home', 'python', 'Process', 'Python364', 'Test2')

        joinpath(*other):连接多个字符串到Path对象中!
                代码:
                file2.joinpath('etc', 'init.d', Path('http')) # 返回一个新的 PosixPath('etc/init.d/http')

    2,获取路径:
        str获取路径字符串:
            print(str(file3))
        bytes获取路径字符串的bytes:
            print(bytes(file3))

    4,父目录:
    file = Path('/etc/init.d/http')
        parent:目录的逻辑父目录
            file.parent # PosixPath('/etc/init.d')
        parents:父目录序列,索引0是直接的父!
            代码:
            for i in file.parents:
                print(i)
            返回:
            /etc/init.d
            /etc
            /
    5,other属性:
    file = Path('/etc/init.d/http.xml')
        name:file.name;目录中的最后一部分 # 'http'
        suffix:file.suffix;目录中最后一个部分的扩展名 # '.xml'
        stem:目录最后一部分,没有后缀名 # 'http'
        suffixes:返回多个扩展名列表 # ['.xml']
        with_suffix(suffix):补充扩展名到路径尾部,返回新的路径,扩展名存在则无效
            # file.with_suffix('.conf') 返回 PosixPath('/etc/init.d/http.conf')
        with_name(name):替换目录最后一个部分并返回一个新的路径
            # file.with_name('nginx.conf') 返回 PosixPath('/etc/init.d/nginx.conf')
        cwd():返回当前工作目录
        home():返回当前家目录
        is_dir():是否是目录, 目录存在返回True
        is_file():是否是普通文件,文件存在返回True
        is_symlink():是否是软连接
        is_socket():是否是socket文件
        is_block_device():是否是块设备
        is_char_device():是否是字符设备
        is_absolute():是否是绝对路径
        resolve():返回一个新的路径,这个新路径就是当前Path对象的绝对路径,如果软链接则直接解析
        absolute():获取绝对路径,但是不解析软连接
        exists():目录或文件是否存在
        rmdir():删除空目录,没有提供判断目录为空的方法
        touch(mode=0o666, exist_ok=True):创建一个文件
        as_uri():将路径返回为URL,例如:file:///etc/passwd
        mkdir(mode=0o777, parents=False, exist_ok=False):
            1,parents:是否创建父目录,递归创建;False时,父目录不存在,抛出异常
            2,exist_ok参数,False时,路径存在,抛出异常;True时,静默模式

        iterdir():迭代当前目录

    6,通配符
        glob(pattern):通配给定的模式
            list(file2.glob('*.txt')) # [PosixPath('sample.txt'), PosixPath('six.txt')]

        rglob(pattern):通配给定的模式,递归目录;返回一个生成器

        match(pattern):模式匹配,成功返回True
            Path('a/b.py').match('*.py') # True

        stat():获取文件的元数据信息

        lstat():如果是符号链接,则显示符号链接本身的文件信息

    7,文件操作
        3.5增加的新函数:
            read_bytes():以'rb'读取路径对应文件,并返回二进制流

            read_text():以'rt'方式读取路径对应文件,返回文本

            Path.write_bytes(data):以'wb'方式写入数据到路径对应文件

            write_text(data, enconding=None, errors=None):以'wt'方式写入字符串到路径对应文件

代码一:读取目录下以.txt结尾的文件的内容?
from pathlib import Path

files = list(Path().glob(‘*.txt’))
for input_file in files:
with open(input_file, ‘r’, newline=”) as filereader:
for row in filereader:
print(“{}”.format(row.strip()))

五,os模块、shutil模块

os模块
    os.name:windows是nt,linux是posix
    os.uname():类unix支持
    sys.platform:windows显示win32,linux显示linux
    os.listdir():返回目录内容列表
    os.stat(path, *, dir_fd=None, follow_symlinks=True):调用了linux系统的stat

    os.chmod(path, mode, *, dir_fd=None, follow_symlinks=True):修改权限信息

    os.chown(path, uid, gid):改变文件的属主、属组,但需要足够的权限

shutil模块:
    文件拷贝:使用打开2个文件对象,源文件读取内容,写入目标文件中完成拷贝过程,但这样丢失stat数据信息??

    copy复制:
        1,copyfileobj(fsrc, fdst[, length]):文件对象的复制,fsrc和fdst是open打开的文件对象,复制内容,fdst要求可写!
            length:指定buffer的大小
        重点:要注意f1文件的指针问题,如果指针在最后,是不是把内容写到目标文件中。
            代码:
            with open('test1', 'r+') as f1:
                f1.write('absfeef\nfefefe')
                f1.flush()
                f1.seek(0) # 调整指针到文件的start处
                with open('test2', 'w+') as f2:
                    shutil.copyfileobj(f1, f2)

        2,shutil.copyfile(src, dst, *, follow_symlinks=True):
            1,复制文件内容,不含元数据;src、dst为文件的路径字符串
            2,本质上调用的是copyfileobj,所以不带元数据二进制内容复制

        3,shutil.copymode(src, dst, *, follow_symlinks=True):
            1,仅仅复制权限

        4,shutil.copystat(src, dst, *, follow_symlinks=True):
            1,复制元数据,stat包含的权限

        5,shutil.copy(src, dst, *, follow_symlinks=True):
            1,复制文件内容、权限和部分元数据,不包含创建时间和修改时间
            2,调用的是copyfile、copymode

        6,shutil.copy2(src, dst, *, follow_symlinks=True):
            1,copy2比copy多了复制全部元数据,但是需要平台支持
            2,本质上调用:copyfile、copystat

        7,shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=<function copy2 at 0x7f3644116510>, ignore_dangling_symlinks=False):
            1,递归复制目录,默认使用copy2
            2,src、dst必须是目录, src必须存在,dst必须不存在
            3,ignore=func:提供一个callable;提供一个函数,它会被调用,src是源目录,names是os.listdir(src)的结果,列出src中的文件名,返回值是要被过滤的文件名的set类型数据!
                代码:
                def ignore(src, names): # 定义一个函数
                    igs = filter(lambda x: x.startwith('a'), names) # filter高阶函数过滤开始为字符'a'的文件,并放到集合中
                    return set(igs)

                shutil.copytree('test', 'test1', ignore=ignore)

        8,shutil.rmtree(path, ignore_errors=False, onerror=None):
            1,递归删除,如同rm -rf危险;慎用
            2,它不是原子操作,有可能删除错误,就会中断并且已经删除的就删除了并不会回退
            ignore_errors:为True,忽略错误;为False或者omitted时,onerror失效!
            onerror:为callable,接受函数function、path和execinfo。
                shutil.rmtree('/home/python/six') # 必须是目录

        9,shutil.move(src, dst, copy_function=<function copy2 at 0x7f3644116510>):
            1,递归移动文件、目录到目标,返回目标
            2,本身使用的是os.rename方法。
            3,如果不支持rename,并且是目录,则是先copytree再删除源目录
            4,默认使用copy2方法
                shutil.move('test1', 'test4')

六,CSV和ini

CSV:csv是一个被行分隔符、列分隔符划分成行和列的文本文件,csv不指定字符编码
    1,行分隔符为\r\n,最后一行可以没有换行符
    2,列分隔符常为逗号或者制表符
    3,每一行称为一条记录record

    CSV模块:

ini文件:ini文件作为配置文件格式
格式:
    [DEFAULT]
    name = mysqld
    1,中括号里面的部分称为section,称为段或者区
    2,每一个section中,都是key、value形成的键值对,key称为option选项

configparser模块:
ConfigParser类:
作用:可以将section当作key,section存储着键值对组成的字典,可以把ini配置文件当作一个嵌套的字典。默认使用的是有序字典。

    read(filenames,encoding=None)
        读取ini文件,可以是单个文件,也可以是文件列表,可以指定文件编码。

    sections()
        返回section列表,缺省section不包括在内

    add_section(section_name)
        增加一个section

    has_section(section_name)
        判断section是否存在

    options(section)
        返回section的所有option,会追加缺省section的option

    has_option(section,option)
        判断section是否存在这个option

    get(section,option,*,raw=False,vars=None[,fallback])
        从指定的段或区的选择上取值,如果找到返回,如果没有找到就去找DEFAULT段有没有

    getint(section,option,*,raw=False,vars=None[,fallback])
    getfloat(section,option,*,raw=False,vars=None[,fallback])
    getboolean(section,option,*,raw=False,vars=None[,fallback])
        上面3个方法和get一样,返回指定类型数据

    items(raw=False,vars=None)
    items(section,raw=False,vars=None)
        没有section,则返回所有section名字及其对象;如果指定section,则返回这个指定的section的键值对组成的二元组。

    set(section,option,value)
        section存在,写入option=value,要求option、value必须是字符串

    remove_section(section)
        移除section及其所有option

    remove_option(section,option)
        移除section下的option

    write(fileobject,space_around_delimiters=True)
        将当前config的所有内容写入fileobject中,一般open函数使用w模式

七,序列化和反序列化:pickle、Json

持久化:即把内存中的对象保存到可永久保存的存储设备中(磁盘)。

  • 设计一套协议,按照某种规则,把内存中数据保存到文件中,文件是一个字节序列,所以必须把数据转换成字节序列,输出到文件,这就是序列化,反之,从文件的字节序列恢复到内存,就是反序列化!

    1. 序列化:serialization

      将内存中对象存储下来,把它变成一个一个字节;二进制

    2. 反序列化:deserialization

      将文件系统中的文件中一个一个字节恢复为内存中对象

  • 序列化保存到文件就是持久化

  • 可以将数据序列化后持久化,或者网络传输;也可以将从文件中或网络接收到的字节序列反序列化。

pickle库:

        Python中的序列化、反序列化模块。
        方法:
            dumps:对象序列化为bytes对象
            dump:对象序列化到文件对象,写入文件
            loads:从bytes对象反序列化
            load:对象反序列化,从文件读取数据

Json模块

Json:是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据。
Json数据类型:
值:双引号中的字符串,数值,true和false,null,对象,数组,这些都是值。

  1. 字符串:由双引号包括起来的任意字符的组合
  2. 数值:正数、负数、整数、浮点数
  3. 对象:无序的键值对的集合:{key1:value1}
    key必须是一个字符串,需要双引号包括这个字符串
    value可以是任意合法的值

  4. 数组:有序的值的集合;格式:[val1,…]

Json模块:

  • Python与Json:Python支持少量内建数据类型到Json类型的转换

    True:true,False:false,None:null,str:string,int:integer,float:float,list:array,dict:object
    

    常用方法:
    import json

    dumps:json编码
    dump:json编码并写入文件
    loads:json解码
    load:从文件读取数据,json解码
    一般json编码的数据很少落地,数据都是通过网络传输。

MessagePack:高效压缩

MessagePack是一个基于二进制高效的对象序列化库,可用于跨语言通信,它可以像json那样,在许多语言之间交换结构对象。

  1. 安装:第三方模块

    pip install msgpack-python

  2. 常用方法:

    packb:序列化对象,提供dumps兼容pickle和json
    unpackb:反序列化对象,提供loads兼容
    pack:序列化对象写入文件对象,提供dump兼容
    unpack:反序列化对象保存到文件对象,提供load兼容
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值