• 第十六天python3 文件IO(二)


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

      readable()    检查文件是否可读
      writeable()   检查文件是否可写
      seekable()   检查文件是否可以进行seek操作
      readline()     读取文件一行
      readlines()   读取文件多行
      getvalue()    无视文件指针,输出文件全部内容

    from io import BytesIO
    bio = BytesIO()
    print(bio.readable(),bio.writable(),bio.seekable())
    bio.write(b'Hello
    Beijing')
    bio.seek(0)
    print(bio.readline())
    print(bio.getvalue())
    bio.close()
    执行结果:
    True True True
    b'Hello
    '
    [b'Hello
    ', b'Beijing']
    b'Hello
    Beijing'

    StringIO操作
    一般来说,磁盘的操作比内存的操作要慢的多,内存足够的情况下,一般的优化思路是少落地,减少磁盘IO的过程,可以大大提高程序运行效率;

    from io import StringIO
    sio = StringIO()
    print(sio.readable(),sio.writable(),sio.seekable())
    sio.write('Hello
    Beijing')
    sio.seek(0)
    print(sio.readline())
    print(sio.getvalue())
    sio.close()
    
    执行结果:
    True True True
    Hello
    
    Hello
    Beijing

    os操作

    path模块

    In [1]: from os import path
    #返回绝对路径
    In [2]: print(path.abspath('/etc/sysconfig/network-scripts/ifcfg-eth0'))
    /etc/sysconfig/network-scripts/ifcfg-eth0
    #返回文件名
    In [3]: print(path.basename('/etc/sysconfig/network-scripts/ifcfg-eth0'))
    ifcfg-eth0
    #返回多个路径中共有的最长路径
    In [4]: print(path.commonprefix(['/etc/sysconfig/network-scripts/ifcfg-eth0','/etc/passwd','/etc/redhat-release']))
    /etc/
    #返回文件路径
    In [5]: print(path.dirname('/etc/sysconfig/network-scripts/ifcfg-eth0'))
    /etc/sysconfig/network-scripts
    #路径存在则返回True,路径不存在则返回False
    In [6]: print(path.exists('/etc/sysconfig/network-scripts/ifcfg-eth0'))
    True
    #把path中包含‘~’的转换成用户目录
    In [7]: print(path.expanduser('~'))
    /root
    #返回最近访问的时间(浮点型秒数)
    In [8]: print(path.getatime('/etc/sysconfig/network-scripts/ifcfg-eth0'))
    1534151273.6877685
    #返回最近文件修改的时间
    In [9]: print(path.getmtime('/etc/sysconfig/network-scripts/ifcfg-eth0'))
    1561868750.23188
    #返回文件创建的时间
    In [10]: print(path.getctime('/etc/sysconfig/network-scripts/ifcfg-eth0'))
    1561868750.23188
    #返回文件的大小,如果文件不存在则返回错误
    In [11]: print(path.getsize('/etc/sysconfig/network-scripts/ifcfg-eth0'))
    200
    #判断是否为绝对路径
    In [12]: print(path.isabs('/etc/sysconfig/network-scripts/ifcfg-eth0'))
    True
    #判断是否为文件,非文件或者文件不存在则为False
    In [13]: print(path.isfile('/network-scripts/ifcfg-eth0'))
    False
    #判断是否为文件,是文件则返回True
    In [14]: print(path.isfile('/etc/sysconfig/network-scripts/ifcfg-eth0'))
    True
    #判断是否为目录
    In [15]: print(path.isdir('/etc/sysconfig/network-scripts'))
    True
    #判断是否为软连接,是软连接则为True
    In [16]: print(path.islink('/etc/sysconfig/network-scripts/ifup-isdn'))
    True
    #判断是否为挂载点
    In [17]: print(path.ismount('/'))
    True
    #把目录和文件拼接成路径
    In [18]: print(path.join('/etc','network','ifconfig'))
    /etc/network/ifconfig
    #返回软连接具体指向的文件路径(/usr/sbin/nginx -> /usr/local/openresty/nginx/sbin/nginx)
    In [19]: print(path.realpath('/usr/sbin/nginx'))
    /usr/local/openresty/nginx/sbin/nginx
    #判断目录或者文件是否相同
    In [20]: print(path.samefile('/etc/sysconfig/network-scripts/ifcfg-eth0','/etc/passwd'))
    False
    #把路径分割成dirname和basename,返回一个元组
    In [21]: print(path.split('/etc/sysconfig/network-scripts/ifcfg-eth0'))
    ('/etc/sysconfig/network-scripts', 'ifcfg-eth0')
    #遍历目录
    In [23]: import os
    
    In [24]: for root,dirs,files in os.walk('/etc/sysconfig/network-scripts',topdown=False):
        ...:     for name in files:
        ...:         print(path.join(root,name))
        ...:     for name in dirs:
        ...:         print(path.join(root,name))
        ...: 
    /etc/sysconfig/network-scripts/route-eth0
    /etc/sysconfig/network-scripts/ifup-ippp
    /etc/sysconfig/network-scripts/ifup-aliases
    /etc/sysconfig/network-scripts/ifdown-ippp
    /etc/sysconfig/network-scripts/ifup-TeamPort
    /etc/sysconfig/network-scripts/ifdown-ppp
    /etc/sysconfig/network-scripts/ifup-ipv6
    /etc/sysconfig/network-scripts/ifup
    /etc/sysconfig/network-scripts/init.ipv6-global
    /etc/sysconfig/network-scripts/ifdown-TeamPort
    /etc/sysconfig/network-scripts/ifdown-ipv6
    /etc/sysconfig/network-scripts/route6-eth0
    /etc/sysconfig/network-scripts/ifup-Team
    /etc/sysconfig/network-scripts/ifdown-isdn
    /etc/sysconfig/network-scripts/ifup-ppp
    In [1]: from os import path
    #path.splitdrive(path)  一般在windows下,返回驱动器名和路径组成的元组
    In [2]: print(path.splitdrive(b'C:UsersSunjingxueDownloads'))
    (b'C:',b'\Users\Sunjingxue\Downloads')

      os.listdir('o:/temp') 返回目录内容列表
      os也有open、read、write等方法,但是太低级,建议使用内建函数open、read、write,使用方法相似;
    示例:
      ln -s test t1 建立一个软连接
      os.stat(path,*,dir_fd=None,follow_symlinks=True) 本质上调用Linux系统的stat;
      path:路径的string或者bytes,或者fd文件描述符;
      follow_symlinks True返回文本本身信息,False且如果是软连接则显示软连接本身;
      os.chmod(path,mode,*,dir_fd=None,follow_symlinks=True)
      os.chmod('test',0o777)
      os.chown(path,uid,gid) 改变文件的属主、属组,但需要足够的权限;

    目录操作

    In [1]: from pathlib import Path
    #返回当前目录下的a/b/c/d
    In [3]: p = Path('a','b','c/d')  
    
    In [4]: print(p)
    a/b/c/d
    #返回根下的etc目录
    In [5]: p = Path('/etc')
    
    In [6]: print(p)
    /etc
    #返回/etc/sys/net/ifcfg目录
    In [7]: a = Path('/etc','sys','net/ifcfg')
    
    In [8]: print(a)
    /etc/sys/net/ifcfg
    #返回当前目录
    In [9]: print(Path())
    .

    路径拼接和分解

    In [21]: from pathlib import Path
    #初始化
    In [22]: fc = Path()
    
    In [23]: fc = fc / 'sys'
    
    In [24]: print(fc)
    sys
    
    In [25]: fd = fc / 'network'
    
    In [26]: print(fd)
    sys/network
    
    In [27]: fe = Path('e/f/g')
    
    In [28]: ff = fd / fe
    
    In [29]: print(ff)
    sys/network/e/f/g
    #parts属性,可以返回路径中的每一个部分
    In [30]: print(ff.parts)
    ('sys', 'network', 'e', 'f', 'g')
    #连接多个字符串到Path对象中
    In [31]: print(ff.joinpath('init','httpd',Path('conf.d')))
    sys/network/e/f/g/init/httpd/conf.d
    In [1]: from pathlib import Path
    
    In [2]: p = Path('/usr/local/openresty/nginx/conf/nginx.conf')
    #获取目录的最后一部分
    In [3]: p.name
    Out[3]: 'nginx.conf'
    #获取目录的最后一部分,没有扩展名
    In [4]: p.stem
    Out[4]: 'nginx'
    #获取目录最后一部分的扩展名
    In [5]: p.suffix
    Out[5]: '.conf'
    #替换目录中的最后一部分,并返回一个新的路径
    In [6]: p.with_name('tomcat.xml')
    Out[6]: PosixPath('/usr/local/openresty/nginx/conf/tomcat.xml')
    #替换目录中最后一部分的扩展名,返回新的路径,扩展名存在则无效;
    In [7]: p.with_suffix('.xml')
    Out[7]: PosixPath('/usr/local/openresty/nginx/conf/nginx.xml')
    #返回多个扩展名列表
    In [8]: print(Path(str(p)+'.xml').suffixes)
    ['.conf', '.xml']
    #给配置文件添加后缀
    In [9]: print(Path(str(p)+'.xml'))
    /usr/local/openresty/nginx/conf/nginx.conf.xml
    In [1]: from pathlib import Path
    
    In [2]: p = Path('/usr/local/openresty/nginx/conf/nginx.conf')
    
    In [13]: print(p)
    /usr/local/openresty/nginx/conf/nginx.conf
    #返回当前工作目录
    In [14]: print(p.cwd())
    /root
    #返回当前家目录
    In [15]: print(p.home())
    /root
    #判断是否为目录
    In [16]: print(p.is_dir())
    False
    #判断是否为文件
    In [17]: print(p.is_file())
    True
    #判断是否为软链接
    In [18]: print(p.is_symlink())
    False
    #判断是否为socket文件
    In [19]: print(p.is_socket())
    False
    #判断是否为块设备
    In [20]: print(p.is_block_device())
    False
    #判断是否为字符设备
    In [21]: print(p.is_char_device())
    False
    #判断是否为绝对路径
    In [22]: print(p.is_absolute())
    True
    In [23]: print(p.resolve())
    /usr/local/openresty/nginx/conf/nginx.conf
    #resolve(),返回一个新的路径,这个新路径就是当Path对象的绝对路径,如果是软链接则直接被解析
    In [24]: f = Path('/usr/sbin/nginx')
    
    In [25]: print(f.resolve())
    /usr/local/openresty/nginx/sbin/nginx
    #absolute() 获取绝对路径,但是推荐使用resolve()
    In [26]: print(p.absolute())
    /usr/local/openresty/nginx/conf/nginx.conf
    #exists()判断目录或者文件是否存在
    In [27]: print(p.exists())
    True
    #rmdir()删除空目录
    In [29]: k = Path('/root/test')
    
    In [30]: k.rmdir()
    
    In [31]: print(k.is_dir())
    False
    #as_uri()将路径返回成URI
    In [32]: print(p.as_uri())
    file:///usr/local/openresty/nginx/conf/nginx.conf
    #touch()创建一个文件
    In [39]: t = Path('/root/test.txt')
    
    In [40]: t.touch(mode=0o666,exist_ok=True)
    #mkdir()创建一个目录
    In [41]: m = Path('/root/testdir')
    
    In [42]: m.mkdir(mode=0o644,parents=False,exist_ok=False)
    
    In [43]: print(m.is_dir)
    <bound method Path.is_dir of PosixPath('/root/testdir')>
    #目录创建成功
    In [44]: print(m.is_dir())
    True
    #文件创建成功
    In [45]: print(t.is_file())
    True
    #parents,是否创建父目录,True等同于mkdir -p;False时,父目录不存在,则抛出FileNotFoundError
    #exist_ok参数,在3.5版本加入,False时,路径存在,则抛出FileExistsError,True时,FileExistsError被忽略
    #目录遍历示例:
    In [58]: f = Path('/usr/sbin/nginx')
    
    In [59]: print(f)
    /usr/sbin/nginx
    
    In [61]: print(f.parents[len(f.parents)-2])
    /usr
    #iterdir()迭代当前目录
    In [65]: it = f.parents[len(f.parents)-2].iterdir()
    
    In [66]: for i in it:
        ...:     print(i)
        ...: 
    /usr/java
    /usr/c6x-uclinux
    /usr/avr32-linux-gnu
    /usr/tilegx-linux
    /usr/h8300-linux-gnu
    /usr/lib
    /usr/hppa64-linux-gnu
    /usr/games
    /usr/local

     通配符

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

    In [1]: from pathlib import Path
    
    In [2]: p = Path('/etc/sysconfig/network-scripts')
    #返回当前目录对象下以ifcfg开头的文件
    In [3]: print(list(p.glob('ifcfg*')))
    [PosixPath('/etc/sysconfig/network-scripts/ifcfg-eth0'), PosixPath('/etc/sysconfig/network-scripts/ifcfg-lo'), PosixPath('/etc/sysconfig/network-scripts/ifcfg-eth0:1')]
    #在root目录下创建3级目录mkdir -pv /root/1/2/3,分别在1/2/3目录下创建1.py、2.py、3.py文件
    In [6]: py = Path('/root/1')
    #递归所有目录,找出以.py结尾的文件,等同于rglob
    In [7]: print(list(py.glob('**/*.py')))
    [PosixPath('/root/1/1.py'), PosixPath('/root/1/2/2.py'), PosixPath('/root/1/2/3/3.py')]
    #rglob()递归所有目录,返回一个生成器;
    In [8]: print(py.rglob('*.py'))
    <generator object Path.rglob at 0x7f9fc04997d8>
    
    In [9]: print(list(py.rglob('*.py')))
    [PosixPath('/root/1/1.py'), PosixPath('/root/1/2/2.py'), PosixPath('/root/1/2/3/3.py')]

    匹配
    match(pattern)
    模式匹配,成功返回True

    In [10]: print(Path('/root/1/1.py').match('*.py'))
    True
    
    In [11]: print(Path('/root/1/2/2.py').match('2/*.py'))
    True
    
    In [12]: print(Path('/root/1/2/2.py').match('1/*.py'))
    False
    
    In [13]: print(Path('/root/1/2/2.py').match('1/*/*.py'))
    True
    
    In [14]: print(Path('/root/1/2/2.py').match('/1/*/*.py'))
    False
    
    In [15]: print(Path('/root/1/2/2.py').match('root/*/*.py'))
    False
    
    In [16]: print(Path('/root/1/2/2.py').match('root/*/*/*.py'))
    True
    
    In [17]: print(Path('/root/1/2/2.py').match('root/**/*.py'))
    False
    
    In [18]: print(Path('/root/1/2/2.py').match('root/**/*/*.py'))
    True
    
    In [19]: print(Path('/root/1/2/2.py').match('**/*.py'))
    True

    获取文件元数据

    stat() 相当于stat命令
    lstat()同stat() 但如果是符号链接,则显示符号链接本身的文件信息;

    In [20]: s = Path('/etc/sysconfig/network-scripts/ifcfg-eth0')
    #相当于Linux的stat命令
    In [21]: print(s.stat())
    os.stat_result(st_mode=33188, st_ino=276105, st_dev=64769, st_nlink=1, st_uid=0, st_gid=0, st_size=200, st_atime=1534151273, st_mtime=1561868750, st_ctime=1561868750)
    #这是一个软连接
    In [22]: l = Path('/usr/sbin/nginx')
    #软链接追踪,显示实际链接文件的信息
    In [23]: print(l.stat())
    os.stat_result(st_mode=33261, st_ino=666280, st_dev=64769, st_nlink=1, st_uid=0, st_gid=0, st_size=16727928, st_atime=1620292430, st_mtime=1619687027, st_ctime=1620292578)
    #显示软连接本身的文件信息
    In [24]: print(l.lstat())
    os.stat_result(st_mode=41471, st_ino=309800, st_dev=64769, st_nlink=1, st_uid=0, st_gid=0, st_size=37, st_atime=1612773100, st_mtime=1612773100, st_ctime=1612773100)
    #/usr/sbin/nginx ---> /usr/local/openresty/nginx/sbin/nginx
    In [25]: ll = Path('/usr/local/openresty/nginx/sbin/nginx')
    #通过23和26就可证明,当stat()获取软链接信息时,获取的是实际文件的信息
    In [26]: print(ll.stat())
    os.stat_result(st_mode=33261, st_ino=666280, st_dev=64769, st_nlink=1, st_uid=0, st_gid=0, st_size=16727928, st_atime=1620292430, st_mtime=1619687027, st_ctime=1620292578)

    文件操作
      使用方法类似内建函数(open(mode='r',buffering= -1,encoding= None,errors=None,newline=None))返回一个文件对象;3.5后增加的新函数;
      read_bytes()
        以‘rb’读取路径对应文件,并返回二进制流;
      read_text(encoding=None,errors=None)
        以‘rt’方式读取路径对应文件,返回文本;
      read_bytes 实际调用的都是open方法;

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

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

    In [27]: from pathlib import Path
    
    In [28]: t = Path('/root/1/1.py')
    
    In [29]: t.write_bytes(b'Beijing Hello')
    Out[29]: 13
    
    In [30]: t.read_bytes()
    Out[30]: b'Beijing Hello'
    
    In [31]: t1 = Path('/root/1/2/2.py')
    
    In [32]: t1.write_text('Hello BeiJing')
    Out[32]: 13
    
    In [33]: t1.read_text()
    Out[33]: 'Hello BeiJing'
    
    In [34]: with t1.open() as f:
        ...:     print(f.read(5))
        ...: 
    Hello

    shutil模块
    该模块不仅仅可以复制文件内容,也可以复制文件的stat信息;还可以复制目录;
    copy复制
      copyfileobj(fsrc,fdist[,length])
        文件对象的复制,fsrc和fdist是open打开的文件对象,复制内容,fdist要求可写;length指定了表示buffer的大小;

    import shutil
    with open('C:/Users/Sunjingxue/Downloads/test.txt','r+') as f:
        f.write('Hello
    BeiJing')
        f.flush()
    #此时指针是在末尾,如果不seek(0),则复制的内容是空;
        print(f.tell())
        f.seek(0)
        with open('C:/Users/Sunjingxue/Downloads/test1.txt','w') as f1:
            shutil.copyfileobj(f,f1)

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

    In [1]: import shutil
    
    In [2]: shutil.copyfile('/root/copyfile.txt','/root/copyfile01,txt')
    Out[2]: '/root/copyfile01.txt'
    
    In [4]: with open('/root/copyfile01.txt') as f:
       ...:     print(f.read())
       ...: 
    Hello BeiJing
    
    In [7]: from pathlib import Path
    
    In [8]: print(Path('/root/copyfile.txt').stat())
    os.stat_result(st_mode=33188, st_ino=407296, st_dev=64769, st_nlink=1, st_uid=0, st_gid=0, st_size=14, st_atime=1620459966, st_mtime=1620459966, st_ctime=1620460023)
    
    In [10]: print(Path('/root/copyfile01,txt').stat())
    os.stat_result(st_mode=33188, st_ino=403577, st_dev=64769, st_nlink=1, st_uid=0, st_gid=0, st_size=14, st_atime=1620460037, st_mtime=1620460037, st_ctime=1620460037)

      copymode(src,dst,*,follow_symlinks=True)
        仅仅复制权限;

    In [1]: from pathlib import Path
    #copyfile.txt的权限是33279,转换成8进制就是777;
    In [2]: print(Path('/root/copyfile.txt').stat())
    os.stat_result(st_mode=33279, st_ino=407296, st_dev=64769, st_nlink=1, st_uid=0, st_gid=0, st_size=14, st_atime=1620459966, st_mtime=1620459966, st_ctime=1620461219)
    #copyfile01.txt的权限是33188,转换成8进制就是644
    In [3]: print(Path('/root/copyfile01.txt').stat())
    os.stat_result(st_mode=33188, st_ino=403577, st_dev=64769, st_nlink=1, st_uid=0, st_gid=0, st_size=14, st_atime=1620461057, st_mtime=1620461057, st_ctime=1620461095)
    
    In [4]: import shutil
    #仅复制权限
    In [5]: shutil.copymode('/root/copyfile.txt','/root/copyfile01.txt')
    #执行完成后copyfile01.txt的权限也哼33279了;
    In [6]: print(Path('/root/copyfile01.txt').stat())
    os.stat_result(st_mode=33279, st_ino=403577, st_dev=64769, st_nlink=1, st_uid=0, st_gid=0, st_size=14, st_atime=1620461057, st_mtime=1620461057, st_ctime=1620461474)
    
    In [7]: oct(33279)
    Out[7]: '0o100777'

      copystat(src,dst,*,follow_symlinks=True)
        复制元数据,stat包含权限,不复制文件内容;

    In [1]: from pathlib import Path
    
    In [2]: print(Path('/root/copyfile.txt').stat())
    os.stat_result(st_mode=33279, st_ino=407296, st_dev=64769, st_nlink=1, st_uid=0, st_gid=0, st_size=14, st_atime=1620459966, st_mtime=1620459966, st_ctime=1620461219)
    
    In [3]: print(Path('/root/copyfile01.txt').stat())
    os.stat_result(st_mode=33188, st_ino=403577, st_dev=64769, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1620461963, st_mtime=1620461963, st_ctime=1620461963)
    
    In [4]: import shutil
    
    In [5]: shutil.copystat('/root/copyfile.txt','/root/copyfile01.txt')
    
    In [6]: print(Path('/root/copyfile01.txt').stat())
    os.stat_result(st_mode=33279, st_ino=403577, st_dev=64769, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1620459966, st_mtime=1620459966, st_ctime=1620462075)

      copy(src,dst,*,follow_symlinks=True)
        复制文件内容,权限和部分元数据,不包括创建时间和修改时间;本质上调用的是copyfile和copymode;
      copy2(src,dst,*,follow_symlinks=True)
        copy2比copy多了复制全部元数据,但是需要平台支持;本质上调用的是copyfile和copystat;
      copytree(src,dst,symlinks=False,ignore=None,copy_function=copy2,ignore_dangling_symlinks=False)
        递归复制目录,默认使用copy2,也就是带更多的元数据复制;src、dst必须是目录,src必须存在,dst必须不存在;
        ignore = func,提供一个callable(src,names)--->ignored_names。提供一个函数名,src是源目录,names是os.listdir(src)的结果,就是列出src中的文件名,返回值是要被过滤的文件名的set类型数据;

    rm删除
      shutil.rmtree(path,ignore_errors=False,onerror=None)
        递归删除,如同rm -rf一样;
      ignore_errors为True,忽略错误;当为False或者omitted时,onerror生效;
        onerror为callable,接受函数function、path和execinfo;
    move移动
      move(src,dst,copy_function=copy2)
        递归移动文件、目录到目标、返回目标;本身使用的是os.rename方法,默认使用copy2方法;

    shutil还有打包功能,生成tar并压缩,支持zip、gz、bz、xz;但是该模块的打包功能还是调用的shell命令,所以实际使用的时候直接用shell命令会更方便;

  • 相关阅读:
    蓝桥杯程序设计 剪格子
    sql中 1<> 1=1的用处
    form表单的6种提交方式
    js中添加监听,判断是什么事件
    angular iFrame加载资源问题
    报表往子报表里传入list
    struts 文件上传
    获取运行时的泛型类型
    Dao层抽取BaseDao
    SSH整合总结
  • 原文地址:https://www.cnblogs.com/zhangzhide/p/14739117.html
Copyright © 2020-2023  润新知