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命令会更方便;