资源操作之文件和目录操作

资源操作之文件和目录操作

1. 基础操作

  1. 打开文件
    open(file, mode=‘r’, buffering=None, encoding=None, errors=None, newline=None, closefd=True)函数有很多参数,只有file参数是必需的,常用的是file,mode,encoding,分别表示:
    1. file:文件描述符,表示要打开的文件;
    2. mode:指定文件打开的模式,包含r(只读)、w(只写)、a(追加),还有b、t、+字符可以与文件打开模式组合使用,分别表示二进制模式、文本模式、读写模式;
    3. encoding:表示返回的数据采用的编码,默认为utf-8;

还有一些不常用的参数:

  • buffering:取值有0,1,>1三个。
    0代表缓冲关闭(只适用于二进制模式);
    1代表行缓冲(只适用于文本模式);
    >1的整数指定缓冲区的大小;
    不指定时,文本文件采用行缓冲,二进制文件采用固定大小的块缓冲;
  • errors:此参数不应在二进制模式下使用,取值有strict和ignore。
    当取strict时,字符编码出错会报错;
    当取ignore时,字符编码出错,程序会忽略,继续执行下面的程序;
  • newline:只对文本模式有效,取值有None、\n、\r、’’、’\r\n’。
    1)在输入时:
    取值为None时,使用通用换行符(\n、\r、’’、’\r\n’),并且返回时转换为\n;
    取值为’‘时,在输入时使用通用换行符(\n、\r、’’、’\r\n’),但是不经转换直接返回;
    如果’‘中定义了值,则以该值为换行符,并返回给调用者;
    2)在输出时:
    如果换行为None,则写入的任何’\n’字符都将转换为系统默认行分隔符os.linesep;
    如果换行符是’‘或’\n’,则不会进行翻译;
    如果换行符是任何其他合法值,则写入的任何’\n’字符都将转换为给定的字符串;
  • closefd:与传入的文件参数有关,默认情况下为True,传入的file参数为文件的文件名;取值为False的时候,file只能是文件描述符;

推荐写法: 使用Python3的标准库,内置函数open()

  • 如果当前目录中存在要打开的文件,则直接将文件作为参数即可;
  • 如果文件位于其他地方,可指定完整路径;
  • 如果指定的文件不存在,会引发异常:FileNotFoundError
# 显式地指定二进制读取模式,获取可读取的文件对象,默认编码模式为utf-8
f = open("pythonCodingGuide/test.py", "rb", encoding="utf-16")

# 指定写入模式,在文件存在时写入文件,不存在时创建文件
f = open("pythonCodingGuide/test.py", "w")

# 指定独占写入模式,在文件已经存在时引发异常:FileExistsError
f = open("pythonCodingGuide/test.py", "x")

# 在写入模式下打开文件时,既有内容将被删除(截断),并从文件开头处开始写入
# 此时可以使用附加模式,不截断,直接在既有文件末尾继续写入
f = open("pythonCodingGuide/test.py", "a")

# '+'可以与其他模式结合使用,表示既可读取也可写入
# 注意:'r+''w+'之间有个重要差别,后者截断文件,前者不会
f = open("pythonCodingGuide/test.py", "r+")
f = open("pythonCodingGuide/test.py", "w+")
1) 关闭资源

python中打开的资源使用完毕后,引用计数垃圾回收,会自动关闭,但是如果出现异常而又没有手动关闭资源,可能会引发一些问题:

  • 相关数据结构会占用内存;
  • 在进程退出之前,文件无法删除;
  • 系统会缓存写入文件的内容,然后慢慢写入文件,如果中途出现异常会丢失,正常关闭资源会将缓存中的内容写入文件;

推荐写法: 使用Python3的标准库,with语句打开资源

  • 将需要打开的文件放在with语句中,这样with语句就会自动关闭文件,不管程序执行中是否产生异常
  • 使用 with语句管理的资源必须是一个实现上下文管理协议的类,这个类的对象可被称为上下文管理器
filename = 'pythonCodingGuide/test.py'
with open(filename, 'r') as fd:
	"""do something"""
	
# with语句也可以处理通过fileinput.input合并的多个文件
import fileinput
with fileinput.input(files=('test.txt', 'info.txt')) as f:
	"""do something"""

一般写法: 使用Python3的标准库,在try-finally语句中使用close()函数显式的关闭

  • 使用finally语句是为了确保程序能够去执行关闭资源的操作,但当finally语句中出现异常时,资源仍有可 能无法正常关闭
f = open('pythonCodingGuide/test.py')
try:
	"""do something"""
finally:
	"""do something"""  # 若此处出现异常,资源没有正常关闭
	f.close()

2. 文件修改

1) 重命名文件

重命名文件
推荐写法: 使用Python3的标准库,os模块的os.rename()函数

  • 需要导入os模块
  • 当指定的文件不存在时,会引发异常:FileNotFoundError
  • 当新的文件名已经存在时,会引发异常:FileExistsError
import os

os.rename("old_file_name", "new_file_name")

一般写法: 使用Python3的标准库,shutil模块的shutil.move()函数

  • 需要导入shutil模块
  • 当指定的文件不存在时,会引发异常:FileNotFoundError
  • 当新的文件名已经存在时,会覆盖原来的文件
import shutil

shutil.move("old_file_name", "new_file_name")
2) 修改文件权限

更新文件权限
推荐写法: 使用Python3的标准库,os模块的chmod()函数

  • 需要导入os模块以及stat模块
import os
import stat

# 添加owner权限
os.chmod("test.txt", stat.S_IRWXU)  # owner拥有全部权限
os.chmod("test.txt", stat.S_IXUSR)  # owner拥有执行权限
os.chmod("test.txt", stat.S_IWUSR)  # owner拥有写权限
os.chmod("test.txt", stat.S_IRUSR)  # owner拥有读权限

# 添加group权限
os.chmod("test.txt", stat.S_IRWXG)  # group拥有所有权限
os.chmod("test.txt", stat.S_IRGRP)  # group拥有读权限
os.chmod("test.txt", stat.S_IWGRP)  # group拥有写权限
os.chmod("test.txt", stat.S_IXGRP)  # group拥有执行权限

# 添加其他用户权限
os.chmod("test.txt", stat.S_IRWXO)  # 其他用户拥有全部权限
os.chmod("test.txt", stat.S_IROTH)  # 其他用户拥有读权限
os.chmod("test.txt", stat.S_IWOTH)  # 其他用户拥有写权限
os.chmod("test.txt", stat.S_IXOTH)  # 其他用户拥有执行权限

# 同时添加多个权限
os.chmod("test.txt", stat.S_IRWXU | stat.S_IRWXO | stat.S_IRWXG)  # mod:777

3. 文件删除

1) 删除文件

删除指定的文件
推荐写法: 使用Python3的标准库,os模块的os.remove()函数

  • 需要导入os模块
  • 当删除的目标文件不存在时,引发异常:FileNotFoundError
  • 当删除的文件正在使用时,引发异常
import os

os.remove("test.txt") # 文件存在且不被占用时,成功删除文件

# 当删除目标不是文件时,引发异常
os.remove("python/test") # 目标是目录,引发异常:PermissionError

推荐写法: 使用Python3的标准库,os模块的os.unlink()函数

  • 需要导入os模块
  • 当删除的目标文件不存在时,引发异常:FileNotFoundError
  • 当删除的文件正在使用时,引发异常
import os

os.unlink("test.txt") # 文件存在且不被占用时,成功删除文件

# 当删除目标不是文件时,引发异常
os.unlink("python/test") # 目标是目录,引发异常:PermissionError
2) 删除目录

删除指定的目录,目录必须是空目录,否则删除失败
推荐写法: 使用Python3的标准库,os模块的os.rmdir()函数

  • 需要导入os模块
import os

# 删除存在的空目录
os.rmdir("python/test")

# 删除的目录不存在时
os.rmdir("java/test")  # 引发异常:FileNotFoundError

# 删除的目录非空时
os.rmdir("PythonCodingGuide/doc")  # 引发异常:OSError: [WinError 145] 目录不是空的

推荐写法: 使用Python3的标准库,os模块的os.removedirs()函数

  • 需要导入os模块
  • 子目录成功删除时,会删除空的父目录
import os

# 删除存在的空目录
os.removedirs("python/test")

# 删除的目录不存在时
os.removedirs("java/test") # 引发异常:FileNotFoundError

# 删除的目录非空时
os.removedirs("PythonCodingGuide/doc")  # 引发异常:OSError: [WinError 145] 目录不是空的
3) 删除目录及其文件和子目录

删除目录及其文件和子目录
推荐写法: 使用Python3的标准库,shutil模块的shutil.rmtree()函数

  • 需要导入shutil模块
import shutil

# 删除存在的目录
shutil.rmtree("python/test")

# 删除的目录不存在时,引发异常
shutil.rmtree("java/test")  # 引发异常:FileNotFoundError

一般写法: 使用Python3的标准库,os模块的os.walk()函数遍历目录,逐一删除

  • 需要导入os模块
  • 能够删除指定目录下的文件和子目录,但是不会删除指定的目录
import os

for root, dirs, files in os.walk("python/test", topdown=False):
	for name in files:
		os.remove(os.path.join(root, name))
	for name in dirs:
		os.rmdir(os.path.join(root, name))

4. 文件检查

1) 判断文件是否存在

判断文件是否存在
推荐写法: 使用Python3的标准库,os模块的os.path.exists()函数

  • 需要导入os模块
  • 可以检查文件或者目录是否存在
import os

# 文件存在时
os.path.exists("doc/resource/file/check/file_exists")  # 结果:True

# 文件不存在时
os.path.exists("doc/resource/file/check/file_not_exists")  # 结果:False

# 当存在和文件同名的目录时,可能命中同名目录,影响判断结果
# 此时可以在文件名上加后缀区分,或者使用os.path.isdir()/os.path.isfile()加以区分
filename = "doc/resource/file/check/file_exists"
os.path.exists("doc/resource/file/check/file_exists.py")  # 结果:True
os.path.isfile(filename) & os.path.exists(filename)  # 结果:True
not os.path.isdir(filename) & os.path.exists(filename)  # 结果:True

推荐写法: 使用Python3的标准库,内置函数exists()

  • 需要导入pathlib模块
  • 可以检查文件或者目录是否存在
from pathlib import Path

# 文件存在时
path = Path("doc/resource/file/check/file_exists")
path.exists()  # 结果:True

# 文件不存在时
path = Path("doc/resource/file/check/file_not_exists")
path.exists()  # 结果:False

# 当存在和文件同名的目录时,可能命中同名目录,影响判断结果
# 此时可以在文件名上加后缀区分,或者使用os.path.isdir()/os.path.isfile()加以区分
path = Path("doc/resource/file/check/file_exists")
path.exists() & path.is_file()  # 结果:True
not path.is_dir() & path.exists()  # 结果:True

path1 = Path("doc/resource/file/check/file_exists.py")
path1.exists()  # 结果:True
2) 判断文件内容是否相等

判断两个文件的内容是否相等
推荐写法: 使用Python3的标准库,filecmp模块的filecmp.cmp()函数

  • 需要导入filecmp模块
  • filecmp.cmp(f1,f2[,shallow]),可选参数shallow指定比较文件时是否需要考虑文件本身的属性,默认为True
  • 当传入的文件内容相等时返回True,不等时返回False
  • 当传入的文件不存在时,引发异常:FileNotFoundError
import filecmp

file1 = "file_exist"
file2 = "file_exist_copy"
filecmp.cmp(file1, file2)  # 结果:True

file3 = "file_not_exist"
filecmp.cmp(file1, file3)  # 引发异常:FileNotFoundError

推荐写法: 使用Python3的标准库,filecmp模块的filecmp.cmpfiles()函数

  • 需要导入filecmp模块
  • filecmp.cmpfiles(dir1,dir2,common[,shallow]),可选参数shallow指定比较文件时是否需要考虑文件本身的属性,默认为True
  • 比较两个文件夹内指定文件(同名文件比较)是否相等,返回包含三个list的元组,分别表示匹配、不匹配以及错误的文件列表,错误的文件是指不存在的、被锁定不可读、无权限读取等无法访问的文件
import filecmp

dir1 = "/pythonTest/work"
dir2 = "/pythonTest/test"

# 两个文件夹内都存在test.py,且内容相同
filecmp.cmp(dir1, dir2, ["test.py"])  # 结果:True

5. 文件移动

1) 移动文件

移动文件
推荐写法: 使用Python3的标准库,shutil模块的shutil.move()函数

  • 需要导入shutil模块
  • 移动文件到指定的目录,当移动的文件不存在、指定目录不存在或指定目录中存在同名文件时,引发异常
import shutil

srcname = "python/src_dir/file_exist"
destname = "python/des_dir"

# 当源文件和指定目录都存在时,移动成功
shutil.move(srcname, destname)

# 当源文件存在,但是指定目录不存在时,将会把文件重命名为指定目录名称
destname1 = "python/des_dir_not_exist"
shutil.move(srcname, destname1)

# 当指定目录存在,但指定目录中已经存在同名文件时,即使源文件不存在同样会引发异常
# shutil.Error: Destination path'python/des_dir/file_exist' already exists
shutil.move(srcname, destname)  

# 当源文件不存在时,引发异常
# FileNotFoundError: [Errno 2] No such file or directory: 'python/src_dir/file_exist'
shutil.move(srcname, destname)
2) 移动目录

移动目录
推荐写法: 使用Python3的标准库,shutil模块的shutil.move()函数

  • 需要导入shutil模块
  • 移动目录及其所有文件、子文件夹到指定的目录
import shutil

srcname = "python/src_dir"
destname = "python/des_dir"

# 当源目录和指定目录都存在时,移动成功
shutil.move(srcname, destname)

# 当源目录存在,但是指定目录不存在时,将会创建指定目录,并把源目录的内容移动到指定目录
destname1 = "python/des_dir_not_exist"
shutil.move(srcname, destname1)

# 当源目录和指定目录都存在,但指定目录中已经存在同名对象时,引发异常
# shutil.Error: Destination path 'python/des_dir/src_dir' already exists
shutil.move(srcname, destname) 

# 当源目录不存在时,引发异常
# FileNotFoundError: [Errno 2] No such file or directory: 'python/src_dir'
shutil.move(srcname, destname)

6. 文件复制

1) 拷贝文件

拷贝文件
推荐写法: 使用Python3的标准库,shutil模块的copyfile()函数

  • 需要导入shutil模块
  • 源和目标都只能是文件
  • 如果目标不可写,复制操作将引发异常
  • 如果目标文件已存在且可写时,覆盖其内容
  • copyfile()调用了copyfileobj()复制内容
import shutil

src_file = "python/test_exist.py"
dst_file = "python/test_copy_not_exist.py"

# 源和目标都是文件,且源对象存在,复制成功
shutil.copyfile(src_file, dst_file)

# 源或者目标不是文件对象时,引发异常
# PermissionError: [Errno 13] Permission denied
dst_file1 = "python/iamdir"
shutil.copyfile(src_file, dst_file1)

# 源文件存在,目标文件已存在但不可写时,引发异常
# PermissionError: [Errno 13] Permission denied
dst_file2 = "python/test1.py"
shutil.copyfile(src_file, dst_file2)

# 如果源和目标都相同,引发异常
# shutil.SameFileError
dst_file3 = "python/test_exist.py"
shutil.copyfile(src_file, dst_file3)

# 当源文件不存在时,引发异常
# FileNotFoundError: [Errno 2] No such file or directory
src_file1 = "python/test_not_exist.py"
shutil.copyfile(src_file1, dst_file)

推荐写法: 使用Python3的标准库,shutil模块的shutil.copy()函数

  • 需要导入shutil模块
  • 源只能是文件,目标可以是文件,也可以是目录
  • 如果当前路径中已存在同名称文件且可写,则直接覆盖掉
  • copy()依次调用了copyfile()和copymode()复制内容的同时复制权限
import shutil

src_file = "python/test_exist.py"
dst_file = "python/test_copy_not_exist.py"

# 复制成功
# 如果目标是目录,且不存在,则copy方法会认为目标是一个文本文件,并复制内容
shutil.copy(src_file, dst_file)

# 源不是文件对象时,引发异常
# PermissionError: [Errno 13] Permission denied
src_file1 = "python/iamdir"
shutil.copy(src_file1, dst_file)

# 源文件存在,目标文件已存在但不可写时,引发异常
# PermissionError: [Errno 13] Permission denied
dst_file2 = "python/test1.py"
shutil.copy(src_file, dst_file2)

# 如果源和目标都相同,引发异常
# shutil.SameFileError
dst_file3 = "python/test_exist.py"
shutil.copy(src_file, dst_file3)

# 当源文件不存在时,引发异常
# FileNotFoundError: [Errno 2] No such file or directory
src_file2 = "python/test_not_exist.py"
shutil.copy(src_file2, dst_file)

推荐写法: 使用Python3的标准库,shutil模块的copy2()函数

  • 需要导入shutil模块
  • copy2()函数和copy()类似,但是调用了copystat()而不是copymode(),因此,复制数据的同时,会复制源文件的访问和修改时间
import shutil

src_file = "python/test_exist.py"
dst_file = "python/test_copy_not_exist.py"

# 复制成功
# 如果目标是目录,且不存在,则copy方法会认为目标是一个文本文件,并复制内容
shutil.copy2(src_file, dst_file)

# 源不是文件对象时,引发异常
# PermissionError: [Errno 13] Permission denied
src_file1 = "python/iamdir"
shutil.copy2(src_file1, dst_file)

# 源文件存在,目标文件已存在但不可写时,引发异常
# PermissionError: [Errno 13] Permission denied
dst_file2 = "python/test1.py"
shutil.copy2(src_file, dst_file2)

# 如果源和目标都相同,引发异常
# shutil.SameFileError
dst_file3 = "python/test_exist.py"
shutil.copy2(src_file, dst_file3)

# 当源文件不存在时,引发异常
# FileNotFoundError: [Errno 2] No such file or directory
src_file2 = "python/test_not_exist.py"
shutil.copy2(src_file2, dst_file)

一般写法: 使用Python3的标准库,shutil模块的shutil.copyfileobj(fsrc, fdst, length=16*1024)函数

  • 需要导入shutil模块
  • 参数是两个文件的指针open(file_path,mode),其中源文件的mode为r,目标文件的mode为w或a
  • 复制源文件的内容
  • 如果当前路径中已存在同名称文件且可写,则直接覆盖掉
  • 可选参数length可以设置缓冲区长度
  • 因为使用了open()函数,因此拷贝完成后最好显式地关闭资源
import shutil

src_file = open("python/src_file_exist.py", "r")
dst_file = open("python/dst_file_not_exist", "w")
try:
	shutil.copyfileobj(src_file, dst_file)
finally:
	src_file.close()
	dst_file.close()
	
# 当源文件不存在时,引发异常
# FileNotFoundError: [Errno 2] No such file or directory
src_file1 = open("python/test_not_exist.py", 'r')
try:
	shutil.copyfileobj(src_file, dst_file)
finally:
	src_file1.close()
	dst_file.close()
	
# 如果源和目标都相同,清空源文件内容
dst_file1 = open("python/src_file_exist.py", "w")
try:
	shutil.copyfileobj(src_file, dst_file1)
finally:
	src_file.close()
	dst_file1.close()

# 源文件存在,目标文件已存在但不可写时,引发异常
# PermissionError: [Errno 13] Permission denied
dst_file2 = open("python/test1.py", "w")
try:
	shutil.copyfileobj(src_file, dst_file2)
finally:
	src_file.close()
	dst_file2.close()
	
# 源不是文件对象时,引发异常
# PermissionError: [Errno 13] Permission denied
src_file2 = open("python/iamdir", "r")
try:
	shutil.copyfileobj(src_file2, dst_file)
finally:
	src_file2.close()
	dst_file.close()
2) 文件拷贝到指定目录

拷贝文件到指定目录
推荐写法: 使用Python3的标准库,shutil模块的shutil.copy()函数

  • 需要导入shutil模块
  • 源只能是文件,目标可以是文件,也可以是目录
  • 如果当前路径中已存在同名称文件且可写,则直接覆盖掉
  • copy()依次调用了copyfile()和copymode()复制内容的同时复制权限 推荐
import shutil

src_file = "python/test_exist.py"
dst_dir = "python/test"

# 复制成功
# 如果目标目录不存在,则copy方法会认为目标是一个文本文件,并复制内容
shutil.copy(src_file, dst_dir)

# 源不是文件对象时,引发异常
# PermissionError: [Errno 13] Permission denied
src_file1 = "python/iamdir"
shutil.copy(src_file1, dst_dir)

# 当源文件不存在时,引发异常
# FileNotFoundError: [Errno 2] No such file or directory
src_file2 = "python/test_not_exist.py"
shutil.copy(src_file2, dst_dir)

推荐写法: 使用Python3的标准库,shutil模块的copy2()函数

  • 需要导入shutil模块
  • copy2()函数和copy()类似,但是调用了copystat()而不是copymode(),因此,复制数据的同时,会复制源文件的访问和修改时间
import shutil

src_file = "python/test_exist.py"
dst_dir = "python/test"

# 复制成功
# 如果目标是目录,且不存在,则copy方法会认为目标是一个文本文件,并复制内容
shutil.copy2(src_file, dst_dir)

# 源不是文件对象时,引发异常
# PermissionError: [Errno 13] Permission denied
src_file1 = "python/iamdir"
shutil.copy2(src_file1, dst_dir)

# 当源文件不存在时,引发异常
# FileNotFoundError: [Errno 2] No such file or directory
src_file2 = "python/test_not_exist.py"
shutil.copy2(src_file2, dst_dir)
3) 文件目录拷贝

将文件目录及其子目录拷贝到某个目录下
推荐写法: 使用Python3的标准库,shutil模块的shutil.copytree()函数

  • 需要导入shutil模块
  • 源和目标都必须是目录,且目标目录必须不存在
import shutil

src_dir = "python/src_dir_exist"
dst_dir = "python/dst_dir_not_exist"

# 当源目录存在,目标目录不存在时,复制成功
shutil.copytree(src_dir, dst_dir)

# 当源目录存在,目标目录已存在时,引发异常
# FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。
dst_dir1 = "python/dst_dir_exist"
shutil.copytree(src_dir, dst_dir1)

# 当源目录不存在时,引发异常
# FileNotFoundError: [WinError 3] 系统找不到指定的路径
src_dir1 = "python/src_dir_not_exist"
shutil.copytree(src_dir1, dst_dir)

# 当源不是一个目录对象时,引发异常
# NotADirectoryError: [WinError 267] 目录名称无效。
src_dir2 = "python/src.py"
shutil.copytree(src_dir2, dst_dir)

7. 文件读写

Python区分文本和二进制I/O:

  1. 文本模式只能读普通文本文件;二进制模式不仅可以读文本文件,还可以读二进制文件(如图片、声音文件);
  2. Python对文件读取采用统一的操作步骤:打开–读取–关闭。
  3. 本章节假定在parent_path路径下已有如下三个文件:
  1. 编码格式为UTF-8的文本文件:read_file_utf-8,文件内容如下:
    hello world!
    This is a UTF-8 text file.
    hello python!
  2. 编码格式为GBK的文本文件:read_file_gbk,文件内容如下:
    你好,世界!
    这是一个GBK编码的文本文件。
    你好,python!
  3. 图片文件:read_img.PNG
1) 以文本模式读文件

推荐写法: 使用Python3的标准库,内置函数:open(file[, mode=‘r’, encoding=None])

  • file用于指定文件路径,若文件不存在,会抛出FileNotFoundError
  • 使用“t”模式即文本模式,设置mode="r"或"rt"或省略,表示以只读方式在文本模式下打开文件
  • encoding是可选参数,用于指定文件编码(只用于文本模式),对于非UTF-8编码格式的文本文件,需要设 置encoding=“xxx”
  • 使用with语句,可以自动调用close()方法关闭文件流
# 读UTF-8编码的文本文件
with open(r"parent_path\read_file_utf-8") as f:
	for line in f:
		"""process line"""

# 读GBK编码的文本文件
with open(r"parent_path\read_file_gbk", encoding="GBK") as f:
	for line in f:
		"""process line"""
2) 以二进制模式读文件

推荐写法: 使用Python3的标准库,内置函数:open(file, mode=‘rb’)

  • file用于指定文件路径,若文件不存在,会抛出FileNotFoundError
  • 使用“b”模式即二进制模式,设置mode=“rb”,表示以只读方式在二进制模式下打开文件
  • 使用with语句,可以自动调用close()方法关闭文件流
# 读图片文件
with open(r"parent_path\read_img.PNG", "rb") as f:
	for line in f:
		"""process line"""
3) 读取文件全部内容(文本文件、二进制文件)

注意:对于大文件,一次性读取文件全部内容并不是明智的,存在撑爆内存的风险
推荐写法: 使用Python3的标准库,IO类内置函数:read()

  • 从流中读取文件全部内容并返回
# 读UTF-8编码的文本文件
with open(r"parent_path\read_file_utf-8") as f:
	print(f.read())
'''
hello world!
This is a UTF-8 text file.
hello python!
'''

# 以二进制模式读文件
with open(r"parent_path\read_img.PNG", mode="rb") as f:
	# b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x0e\x00\x00"
	print(f.read())

推荐写法: 使用Python3的标准库,IO类内置函数:readlines()

  • 从流中读取文件全部内容,返回一个list,其中每一行作为list的一个元素
  • 本质是循环调用函数readline(),并返回读取的行列表
# 读gbk编码的文本文件
with open(r"parent_path\read_file_gbk", encoding="GBK") as f:
	print(f.readlines())
# ['你好,世界!\n', '这是一个GBK编码的文本文件。\n', '你好,python!']

# 以二进制模式读文件
with open(r"parent_path\read_img.PNG", mode="rb") as f:
# [b'\x89PNG\r\n', b'\x1a\n', b"\x00\x00\x00\rIHDR\x00\x00\x00\x0e\x00\x00"]
	print(f.readlines())
4) 读取一行内容(文本文件、二进制文件)

推荐写法: 使用Python3的标准库,IO类内置函数:readline()

  • 从流中读取一行内容并返回
# 以文本模式读文件
with open(r"parent_path\read_file_utf-8") as f:
	print(f.readline())
'''
hello world!
'''

# 以二进制模式读文件
with open(r"parent_path\read_img.PNG", mode="rb") as f:
	print(f.readline())  # b'\x89PNG\r\n'
5) 读取指定size的内容(文本文件、二进制文件)

推荐写法: 使用Python3的标准库,IO类内置函数:read(size)

  • size用于指定读取的字节数,读取的内容最多不超过size大小
  • 若size<0,则返回文件全部内容;若size=0,则返回空
  • 若size>0,则返回size大小的内容(若size超过文件容量则返回文件全部内容) 推荐
# 以文本模式读文件
with open(r"parent_path\read_file_gbk", encoding="GBK") as f:
	print(f.read(8))
'''
你好,世界!
这
'''

# 以二进制模式读文件
with open(r"parent_path\read_img.PNG", mode="rb") as f:
	print(f.read(8))  # b'\x89PNG\r\n\x1a\n'

推荐写法: 使用Python3的标准库,IO类内置函数:readlines(size)

  • 返回一个list,其中每一行作为list的一个元素,读取的内容最多不超过size大小
  • 本质是循环调用函数readline(),并返回读取的行列表
# 以文本模式读文件
with open(r"parent_path\read_file_utf-8") as f:
	print(f.readlines(15))  # ['hello world!\n', 'This is a UTF-8 text file.\n']

# 以二进制模式读文件
with open(r"parent_path\read_img.PNG", mode="rb") as f:
	print(f.readlines(6))  # [b'\x89PNG\r\n', b'\x1a\n']
6) 读取指定位置的内容(文本文件、二进制文件)

推荐写法: 使用Python3的标准库,IO类内置函数:seek(offset[, whence])

  • 用于改变文件指针的位置
  • offset用于指定偏移量,whence是可选参数,用于指定偏移量的相对位置,值只能是0,1,2
  • 若whence=0(默认),表示相对于文件开始位置偏移,则应该设置offset>=0
  • 若whence=1,表示相对于当前位置偏移,则offset正负均可
  • 若whence=2,表示相对于文件结束位置偏移,则应该设置offset<0
  • 若使用“t”模式选项打开文件,则只允许从文件开始位置偏移,否则会抛出UnsupportedOperation
  • 若使用“b”模式选项打开文件,则上述三种情况均可
  • 使用IO类内置函数tell()可以获取文件指针的位置,返回一个整数
# 以文本模式读文件
with open(r"parent_path\read_file_utf-8") as f:
	f.seek(4, 0)
	print(f.tell())  # 4
	print(f.read(8))  # o world!
	
# 以二进制模式读文件
with open(r"parent_path\read_file_utf-8", mode="rb") as f:
	f.seek(4, 0)
	print(f.tell())  # 4
	print(f.read(8))  # b'o world!'
	
	f.seek(4, 1)
	print(f.tell())  # 16
	print(f.read(8))  # b'is is a
	print(f.tell())  # 24
	
	f.seek(-16, 1)
	print(f.tell())  # 8
	print(f.read(8))  # b'rld!\r\nTh'
	print(f.tell())  # 16
	
	f.seek(-8, 2)
	print(f.tell())  # 47
	print(f.read())  # b' python!'
7) 以文本模式写文件

**推荐写法: 使用Python3的标准库,内置函数:open(file, mode=‘w’[, encoding=None])和IO类内置函数:write(str) **

  • file用于指定文件路径,若文件不存在,则创建该文件(默认是UTF-8编码)
  • 使用“t”模式即文本模式,设置mode="w"或"wt"或省略,表示以只写方式在文本模式下打开文件
  • 若mode=“w”,若文件已存在,则会清除并覆盖掉其内容
  • 若mode=“a”,若文件已存在,则新的内容会被追加到已有内容之后
  • 对于非UTF-8编码格式的文本文件,需要设置encoding=“xxx”
  • 使用with语句,可以自动调用close()方法关闭文件流
  • write(str)函数用于写入一个字符串
# 创建UTF-8编码文件write_file,写入"hello world!"
with open(r"parent_path\write_file", mode="w") as f:
	f.write("hello world!")
	
# 文件内容存在,将其覆盖掉,写入"hello world again."
with open(r"parent_path\write_file", mode="w") as f:
	f.write("hello world again.")
	
# 文件内容存在,追加"\nhello python!"
with open(r"parent_path\write_file", mode="a") as f:
	f.write("\nhello python!")
	
# 创建GBK编码文件write_file_gbk,写入"你好,世界!"
with open(r"parent_path\write_file_gbk", mode="w", encoding="GBK") as f:
	f.write("你好,世界!")
8) 以二进制模式写文件

推荐写法: 使用Python3的标准库,内置函数:open(file, mode=‘wb’)

  • 使用“b”模式即二进制模式,设置mode=“wb”,用法同上
# 创建UTF-8编码文件write_file,写入"hello world!"
with open(r"parent_path\write_file_byte", mode="wb") as f:
	f.write(b'abc')
9) 写入一个字符串

推荐写法: 使用Python3的标准库,IO类内置函数:write(str)

  • 用于写入一个字符串
# 创建UTF-8编码文件write_file,写入"hello world!"
with open(r"parent_path\write_file", mode="wt", encoding="UTF-8") as f:
	f.write("hello world!")
10) 写入多个字符串

推荐写法: 使用Python3的标准库,IO类内置函数:writelines(lines)

  • lines用于接收一个字符串列表或一个字符串
  • 若lines是字符串列表,可用于写入多个字符串,不会自动换行,如果需要,必须自己制定换行符,
  • 若列表中字符串的末尾都没有换行符,则相当于写入了一行数据 若lines是字符串,则用法同write(str),可写入一个字符串
# 写入一个字符串
with open(r"parent_path\write_lines", mode="wt", encoding="UTF-8") as f:
	f.writelines("hello world!")
	
# 以追加模式写入多行字符串
with open(r"parent_path\write_lines", mode="at", encoding="UTF-8") as f:
	f.writelines(["hello,python!\n", "hello,IO!"])

8. 路径判断

1) 判断是否为目录

推荐写法: 使用Python3的标准库,os模块的os.path.isdir()函数

  • 需要导入os模块
import os

path = Path('/CODE/pythonCodeGuide/PythonCodingGuide')
if os.path.isdir(path):  # 返回True
'''路径是一个目录'''

path = Path('pythonCodeGuide/PythonCodingGuide')
# 路径不存在时,返回False
if os.path.isdir(path):
'''路径不存在'''

path = Path('/CODE/pythonCodeGuide/PythonCodingGuide/main.py')
# 路径不是目录时,返回False
if os.path.isdir(path):
'''路径不是一个目录'''

推荐写法: 使用Python3的标准库,内置函数is_dir()

path = Path('/CODE/pythonCodeGuide/PythonCodingGuide')
if path.is_dir(): # 返回True
'''路径是一个目录'''

path = Path('pythonCodeGuide/PythonCodingGuide')
# 路径不存在时,返回False
if path.is_dir():
'''路径不存在'''

path = Path('/CODE/pythonCodeGuide/PythonCodingGuide/main.py')
# 路径不是目录时,返回False
if path.is_dir():
'''路径不是一个目录'''
2) 判断是否为文件

推荐写法: 使用Python3的标准库,os模块的os.path.isfile()函数

  • 需要导入os模块
import os

path = Path('/CODE/pythonCodeGuide/PythonCodingGuide/main.py')
if os.path.isfile(path): # 返回True
'''路径是一个文件'''

path = Path('pythonCodeGuide/PythonCodingGuide')
# 路径不存在时,返回False
if os.path.isfile(path):
'''路径不存在'''

path = Path('/CODE/pythonCodeGuide/PythonCodingGuide')
# 路径不是文件时,返回False
if os.path.isfile(path):
'''路径不是一个文件'''

推荐写法: 使用Python3的标准库,内置函数is_file()

path = Path('/CODE/pythonCodeGuide/PythonCodingGuide/main.py')
if path.is_file(): # 返回True
'''路径是一个文件'''

path = Path('pythonCodeGuide/test')
# 路径不存在时,返回False
if path.is_file():
'''路径不存在'''

path = Path('/CODE/pythonCodeGuide/PythonCodingGuide')
# 路径不是文件时,返回False
if path.is_file():
'''路径不是一个文件'''
3) 判断path是否存在

推荐写法: 使用Python3的标准库,os模块的os.path.exists()函数

  • 需要导入os模块
import os

path = Path('/CODE/pythonCodeGuide/PythonCodingGuide')
# 路径存在,返回True
if os.path.exists(path):
'''路径存在'''

path = Path('/pythonCodeGuide/PythonCodingGuide')
# 路径不存在,返回False
if os.path.exists(path):
'''路径不存在'''

推荐写法: 使用Python3的标准库,内置函数exists()

path = Path('/CODE/pythonCodeGuide/PythonCodingGuide')
# 路径存在,返回True
if path.exists():
'''路径存在'''

path = Path('/pythonCodeGuide/PythonCodingGuide')
# 路径不存在,返回False
if path.exists():
'''路径不存在'''
4) 判断是否为绝对路径

推荐写法: 使用Python3的标准库,os模块的os.path.isabs()函数

  • 需要导入os模块
  • 即使目标路径是不存在的,只要命名对象是绝对路径,就返回True
import os

path = Path("D:/pythonCodeGuide/test")
# 当是绝对路径时,返回True
if os.path.isabs(path):
'''是绝对路径'''

path = Path("/pythonCodeGuide/test")
# 当不是绝对路径时,返回False
if os.path.isabs(path):
'''不是绝对路径'''

推荐写法: 使用Python3的标准库,内置函数is_absolute()

  • 即使目标路径是不存在的,只要命名对象是绝对路径,就返回True
path = Path("D:/pythonCodeGuide/test")
# 当是绝对路径时,返回True
if path.is_absolute():
'''是绝对路径'''

path = Path("/pythonCodeGuide/test")
# 当不是绝对路径时,返回False
if path.is_absolute():
'''不是绝对路径'''
5) 判断是否为符号链接

推荐写法: 使用Python3的标准库,os模块的os.path.islink()

  • 如果文件不存在,os.path.islink()返回False
import os

# iamfile-s -> /CODE/pythonCodeGuide/PythonCodingGuide/doc/resource/iamfile

path = Path("/CODE/pythonCodeGuide/PythonCodingGuide/iamfile-s")
# 当对象是一个符号链接时,返回True
if os.path.islink(path):
'''是一个符号链接'''

path = Path("/CODE/pythonCodeGuide/PythonCodingGuide/doc/resource/iamfile")
# 当对象不是一个符号链接时,返回False
if os.path.islink(path):
'''不是一个符号链接'''

推荐写法: 使用Python3的标准库,内置函数is_symlink()

  • 如果文件不存在,os.path.islink()返回False
# iamfile-s -> /CODE/pythonCodeGuide/PythonCodingGuide/doc/resource/iamfile

path = Path("/CODE/pythonCodeGuide/PythonCodingGuide/iamfile-s")
# 当对象是一个符号链接时,返回True
if path.is_symlink():
'''是一个符号链接'''

path = Path("/CODE/pythonCodeGuide/PythonCodingGuide/doc/resource/iamfile")
# 当对象不是一个符号链接时,返回False
if path.is_symlink():
'''不是一个符号链接'''
6) 判断是否为目录的符号链接

推荐写法: 使用Python3的标准库,判断是否为目录的符号链接

def is_dir_symlink(location):
	"""第一步:转换为path
	   第二步:path为符号链接文件
	   第三步:判断符号链接的目标文件是否是目录"""
	path = Path(location)
	if not path.exists():
		return False
	return path.is_symlink() & path.is_dir()
	# 或者引入os模块 return os_path_islink() & os.path.isdir()

# iamdir-s -> /CODE/pythonCodeGuide/PythonCodingGuide/doc/resource/iamdir

# 对象为符号链接,且为目录的符号链接
is_dir_symlink("/CODE/pythonCodeGuide/PythonCodingGuide/iamdir-s")  # 结果:True
# 对象不是符号链接
is_dir_symlink("/CODE/pythonCodeGuide/PythonCodingGuide/iamdir-h")  # 结果:False
# 对象不存在
is_dir_symlink("/CODE/pythonCodeGuide/PythonCodingGuide/iamdir_not_exist")  # 结果:False
7) 判断是否为文件的符号链接

推荐写法: 使用Python3的标准库,判断是否为文件的符号链接

def is_file_symlink(location):
	"""第一步:转换为path
	   第二步:path为符号链接文件
	   第三步:判断符号链接的目标文件是否是文件"""
	path = Path(location)
	if not path.exists():
		return False
	return path.is_symlink() & path.is_file()
	# 或者引入os模块 return os_path_islink() & os.path.isfile()
	
# iamfile-s -> /CODE/pythonCodeGuide/PythonCodingGuide/doc/resource/iamfile

# 对象为符号链接,且为文件的符号链接
is_file_symlink("/CODE/pythonCodeGuide/PythonCodingGuide/iamfile-s")  # 结果:True
# 对象为普通文件
is_file_symlink("/CODE/pythonCodeGuide/PythonCodingGuide/iamfile-h")  # 结果:False
# 对象文件不存在
is_file_symlink("/CODE/pythonCodeGuide/PythonCodingGuide/iamfile_not_exist")  # 结果:False

8. 目录创建

1) 创建单个目录

推荐写法: 使用Python3的标准库,os模块的函数:os.mkdir(path[, mode=0o777])

  • 需要导入os模块
  • 用于在已存在的目录中创建一个文件夹,path指代一个文件夹名或路径,mode为权限模式(因平台而异)
  • 若path是文件夹名,则默认在当前目录下创建
  • 若path包含路径,则必须给出一个已存在的父路径,否则会抛出FileNotFoundError
  • 若路径中包含转义字符,可使用双斜线“\”或“r”前缀,消除转义字符
  • 若目标文件夹已存在,会抛出FileExistsError
import os

os.mkdir("dir1")  # 在当前目录下创建dir
# 抛出FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。: 'dir1'
os.mkdir("dir1")

# 抛出FileNotFoundError: [WinError 3] 系统找不到指定的路径。: '\\test\\dir1'
os.mkdir("\\test\\dir1")

# 在parent_path下创建dir2
os.mkdir(r"parent_path\dir2")
2) 创建多级目录

推荐写法: 使用Python3的标准库,os模块的函数:os.makedirs(name [, mode=0o777, exist_ok=False])

  • 需要导入os模块
  • 用于递归创建一个或多个文件夹,name指代一个文件夹名或路径,mode为权限模式
  • 若name是文件夹名,则默认在当前目录下创建
  • 若name包含路径,则会递归创建所有给出的不存在的文件夹
  • 若目标文件夹已存在:exists_ok=False(默认),抛出FileExistsError;exists_ok=True,不会抛出异常
import os

os.makedirs("dir1")  # 在当前目录下创建dir
# 抛出FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。: 'dir1'
os.makedirs("dir1")

os.makedirs("dir1", exist_ok=True)  # 设置exist_ok=True,当目标文件夹已存在,不会抛出异常
os.makedirs("test\\dir2")  # 在当前目录下创建test,在test下创建dir2
os.makedirs(r"parent_path\dir3")  # 创建"parent_path\\dir3"路径上所有不存在的文件夹

9. 目录操作

1) 目录遍历

推荐写法: 使用Python3的标准库,os模块的函数:os.walk(top[, topdown=True, οnerrοr=None,followlinks=False])

  • 需要导入os模块
  • 递归遍历指定路径,返回一个(dirpath, dirnames, filenames)三元组
  • dirpath是一个字符串,表示目录的路径;dirnames是一个列表,包含了dirpath下所有的一级目录的名字(不包含子目录);filenames是一个列表,包含了dirpath下所有的文件的名字(不包含子目录),使用函数os.path.join(dirpath, name)可得到文件的全路径
  • top指定要遍历的目录的路径,其它三个是可选参数,topdown指定递归遍历的顺序,onerror指定异常时的回调函数
  • 若topdown=True(默认),则自顶向下深度遍历目录树,先遍历父目录,再遍历子目录
  • 若topdown=False,则自底向上遍历目录树,先遍历子目录,再遍历父目录
import os

# 自顶向下遍历目录树
for dirpath, dirnames, filenames in os.walk("parent_path\\path"):
	print(dirpath)  # 返回一个string,表示目录的路径
	print(dirnames)  # 返回一个list,包含了dirpath下所有的一级目录名
	print(filenames)  # 返回一个list,包含了dirpath下所有的文件名
	
	for name in filenames:
		print(os.path.join(dirpath, name))  # 获取top目录下所有文件的全路径(包括子目录)
2) 列举目录下所有文件(不包含子文件夹)

获取文件夹下的所有文件(不包含子文件夹)
推荐写法: 使用Python3的标准库,os模块的os.listdir()函数

  • 需要导入os模块
  • os.listdir()函数会列出目标目录下所有文件以及子目录名称
  • 使用os.path.isfile()函数筛选出其中的文件
import os

file_list = [f for f in os.listdir("/pythonTest/work") if os.path.isfile(os.path.join("/pythonTest/work", f))]

# 也可以写成如下形式
for filename in os.listdir("/pythonTest/work"):
	if os.path.isfile(filename):
		print(filename)

推荐写法: 使用Python3的标准库,os模块的os.walk()函数

  • 需要导入os模块
  • 递归遍历指定路径,返回一个(dirpath, dirnames, filenames)三元组,如果只需要顶层目录下的文件,只需要在第一次迭代后break即可
import os

file_list = []
for (dirpath, dirnames, filenames) in os.walk("/pythonTest/work"):
	file_list.extend(filenames)
	break
3) 列举目录下所有文件(包含子文件夹)

获取文件夹下的所有文件(包含子文件夹)
推荐写法: 使用Python3的标准库,os模块的os.walk()函数

  • 需要导入os模块
  • 递归遍历指定路径,返回一个(dirpath, dirnames, filenames)三元组,如果只需要文件名,取出filenames即可
import os

file_list = []
for (dirpath, dirnames, filenames) in os.walk("/pythonTest/work"):
	file_list.extend(filenames)

一般写法: 使用Python3的标准库,os模块的os.listdir()函数

  • 需要导入os模块
import os

def print_files(path):
	"""第一步:os.listdir()函数列出目标目录下所有的文件和子目录;
       第二步:dirs返回当前目录下的所有目录,递归dirs直到最深一层;
  	   第三步:打印所有文件名"""
	lsdir = os.listdir(path)
	dirs = [i for i in lsdir if os.path.isdir(os.path.join(path, i))]
	if dirs:
		for i in dirs:
			print_files(os.path.join(path, i))
	files = [i for i in lsdir if os.path.isfile(os.path.join(path, i))]
	for f in files:
		print(f)
		
print_files("/pythonTest/work")
4) 列举当前目录下符合条件的文件

获取当前目录下符合条件的文件名
推荐写法: 使用Python3的标准库,glob模块的glob.glob()函数

  • 需要导入glob模块
  • 返回目录下符合条件的文件名的列表
  • 不包含子目录下的文件
import glob

# 获取顶层目录下所有python文件名
glob.glob("/pythonTest/work/*.py")

推荐写法: 使用Python3的标准库,os模块的os.walk()函数

  • 需要导入os模块
  • 获取所有文件后筛选出符合条件的文件
  • 若需要包含子目录下的文件,去掉break即可
import os

# 筛选出顶层目录下的python文件
file_list = []
for (dirpath, dirnames, filenames) in os.walk("/pythonTest/work"):
	for item in filenames:
		if ".py" in item:
			file_list.append(item)
	break
print(file_list)
5) 列举目录下所有子目录

获取文件夹下的所有子目录
推荐写法: 使用Python3的标准库,os模块的os.listdir()函数

  • 需要导入os模块
  • os.listdir()函数会列出目标目录下所有文件以及子目录名称
  • 使用os.path.isdir()函数筛选出其中的目录
import os

"""只包含顶层目录下的子目录"""
dir_list = [f for f in os.listdir("/pythonTest/work") if os.path.isdir(os.path.join("/pythonTest/work", f))]

# 也可以写成如下形式
for filename in os.listdir("/pythonTest/work"):
	if os.path.isdir(filename):
		print(filename)

"""获取目录下的所有子目录名称"""
def print_files(path):
	lsdir = os.listdir(path)
	dirs = [i for i in lsdir if os.path.isdir(os.path.join(path, i))]
	if dirs:
		for i in dirs:
			print_files(os.path.join(path, i))
	sub_dirs = [i for i in lsdir if os.path.isdir(os.path.join(path, i))]
	for f in sub_dirs:
		print(f)
		
print_files("/pythonTest/work")

推荐写法: 使用Python3的标准库,os模块的os.walk()函数

  • 需要导入os模块
  • 递归遍历指定路径,返回一个(dirpath, dirnames,filenames)三元组,如果只需要顶层目录下的目录,只需要在第一次迭代后break即可
import os

"""只包含顶层目录下的子目录"""
dir_list = []
for (dirpath, dirnames, filenames) in os.walk("/pythonTest/work"):
	dir_list.extend(dirnames)
	break
	
"""获取目录下的所有子目录名称"""
dir_list = []
for (dirpath, dirnames, filenames) in os.walk("/pythonTest/work"):
	dir_list.extend(dirnames)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值