社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

深度对比Python中4大文件/文件夹处理库,你更pick哪一个?

happy科研 • 3 年前 • 428 次点击  

一、开篇

os库应该是使用频率最高的一个文件处理库,但是不得不说Python中还有几个其它的文件处理库,像shutil库glob库pathlib库,它们可以说是相互补充,有着自己好用的方法。黄同学亲切的将它们合称为Python文件处理库的四大天王
今天呢,咋们就对这4个库来个深度对比,对比一下好像学习什么都快了。

二、四大库各自好用的地方

这里采用文字叙述为大家讲解这四大模块各自的用法,具体内容会在后面详细介绍。

1. os库

对于os模块来说,这是大家最熟悉的一个库,功能相对很齐全,主要像以下这些功能:
  • os.getcwd():获取当前的工作路径;
  • os.chdir() :改变当前工作目录到指定的路径;
  • os.listdir(path):传入任意一个path路径,返回的是该路径下所有文件和目录组成的列表;
  • os.mkdir():创建文件夹;

2. shutil库

shutil库,最主要的功能就是提供了对文件/文件夹的复制、移动和删除功能,主要如下:
  • shutil.copy(src,dst):复制文件,src表示源文件,dst表示目标文件夹;
  • shutil.copytree(src,dst):复制文件夹,src表示源文件夹,dst表示目标文件夹;
  • shutil.move(src,dst):移动文件/文件夹,src表示源文件/文件夹,dst表示目标文件夹;
  • shutil.rmtree(src):删除文件夹,src表示源文件夹。区别这里和os模块中remove() 、rmdir()的用法、remove()方法只能删除某个文件,mdir()只能删除某个空文件夹。但是shutil模块中的rmtree()可以递归彻底删除非空文件夹;

3. glob库

glob库,提供了更加便捷的用来查找符合特定规则的目录和文件的方法,主要它支持*、**、? 、[ ]这四个通配符。
  • *:匹配0个或多个字符;
  • **:匹配所有文件、目录、子目录和子目录里的文件(3.5版本新增);
  • ?:匹配一个字符;
  • []:匹配指定范围内的字符,如[0-9]匹配数字,[a-z]匹配小写字母;

4. pathlib库

pathlib库中有一些功能超级棒,其中我最喜欢下面这个功能:
  • p.name:获取文件名;
  • p.suffix:获取文件后缀;
有了上述说明,下面详细为大家介绍4个库它们各自的用法。

三、os库

1. 模块的安装和导入

# 导入
import os

2. os.getcwd()

  • 作用:获取当前的工作路径;
os.getcwd()
结果如下:

3. os.listdir(path)

  • 作用:传入任意一个path路径,返回的是该路径下所有文件和目录组成的列表;
path = r"C:\Users\黄伟\Desktop\publish\os模块\test_os模块"
os.listdir(path)
结果如下:

4. os.walk(path)

  • 含义 :传入任意一个path路径,深层次遍历指定路径下的所有子文件夹,返回的是一个由路径、文件夹列表、文件列表组成的元组。我代码中写的方式属于元组拆包
  • 元组拆包:就是将一个元组中的每个值,赋值给不同的变量;
path = r"C:\Users\黄伟\Desktop\publish\os模块\test_os模块"
for path,dirs,files in os.walk(path):
    print(path)
    print(dirs)
    print(files)
    print("\n")
结果如下:

5. os.path.exists(path)

  • 含义:传入一个path路径,判断指定路径下的目录是否存在。存在返回True,否则返回False;
path1 = 'C:\\Users\\黄伟\\Desktop\\publish\\os模块\\huang_wei'

if os.path.exists(path1):
    print("指定文件夹存在")
else:
    print("指定文件夹不存在")
结果如下:

6. os.mkdir(path)

  • 含义:传入一个path路径,创建单层(单个)文件夹;
  • 注意:如果文件夹已经存在,就会报错。因此创建文件夹之前,需要使用os.path.exists(path)函数判断文件夹是否存在;
os.getcwd()
path1 = os.getcwd()+"\\huang_wei"
os.mkdir(path1)
结果如下:

7. os.makedirs(path)

  • 含义:传入一个path路径,生成一个递归的文件夹;
  • 注意:如果文件夹存在,就会报错。因此创建文件夹之前,需要使用os.path.exists(path)函数判断文件夹是否存在;
os.getcwd()
path1 = os.getcwd()+"\\huang_wei"
os.mkdir(path1)
结果如下:

8. os.rmdir(path)

  • 含义:传入一个path路径,删除指定路径下的文件夹;
  • 注意:该方法只能删除空文件夹,删除非空文件夹会报错;
path1 = os.getcwd()+"\\huang_wei"
os.rmdir(path1)
----------------------------------
path2 = os.getcwd()+"\\a\\b\\c"
os.rmdir(path2) 
结果如下:

9. os.path.join(path1,path2)

  • 含义:传入两个path路径,将该路径拼接起来,形成一个新的完整路径;
path = os.getcwd()
lis = ["a.jpg","b.jpg","c.jpg"]
for i in lis:
    x = os.path.join(path,i)
    print(x)
结果如下:

10. os.path.split(path)

  • 含义:传入一个完整的path路径,将其拆分为绝对路径文件名2部分;
path1 = r"C:\Users\黄伟\Desktop\publish\os模块\a.jpg"
os.path.split(path1)
结果如下:

11. os.path.dirname(path)

  • 含义:传入一个完整的文件路径,只获取其绝对路径;



    
path1 = r"C:\Users\黄伟\Desktop\publish\os模块\a.jpg"
os.path.dirname(path1)
结果如下:

12. os.path.basename(path)

  • 含义:传入一个完整的文件路径,只获取其文件名;
path1 = r"C:\Users\黄伟\Desktop\publish\os模块\a.jpg"
os.path.basename(path1)
结果如下:

13. os.path.isdir(path)

  • 含义:传入一个完整的文件路径,判断它是否是文件夹;
path = os.getcwd()
file_list = os.listdir()
for file in file_list:
    if os.path.isdir(file):
        print(file)
结果如下:

14. os.path.isfile(path)

  • 含义:传入一个完整的文件路径,判断它是否是文件;
path = os.getcwd()
file_list = os.listdir()
for file in file_list:
    if os.path.isfile(file):
        print(file)
结果如下:

15. os.path.sep

  • 含义:返回当前操作系统的路径分隔符;
os.path.sep
结果如下:

16. os.path.getsize(path)

  • 含义:传入一个完整的文件路径,返回该文件的大小;
os.path.getsize("我创建的压缩包.zip")
结果如下:

四、shutil库

本文所使用的素材,都是基于以下2个文件夹,其中一个文件夹为空。

1. 模块导入

import shutil

2. 复制文件

  • 函数:shutil.copy(src,dst)
  • 含义:复制文件;
  • 参数:src表示源文件,dst表示目标文件夹;
  • 注意:当移动到一个不存在的“目标文件夹”,系统会将这个不存在的“目标文件夹”识别为新的文件夹,而不会报错;
# 1.将a表的“data.txt”移动到b表
src = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a\data.txt"
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_b"

shutil.copy(src,dst)
------------------------------------------------------------
# 2.将a表的“data.txt”移动到b表,并重新命名为“new_data.txt”
src = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a\data.txt"
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_b\new_data.txt"

shutil.copy(src,dst)
------------------------------------------------------------
# 3.将a表的“data.txt”移动到“不存在”的文件夹
src = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a\data.txt"
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_c"

shutil.copy(src,dst)
"""
注意:对于情况3,系统会默认将“test_shutil_c”识别为文件名,而不是按照我们认为的,移动到一个新的不存在的文件夹。
"""
结果如下:

3. 复制文件夹

  • 函数:shutil.copytree(src,dst)
  • 含义:复制文件夹;
  • 参数:src表示源文件夹,dst表示目标文件夹;
  • 注意:这里只能是移动到一个空文件夹,而不能是包含其他文件的非空文件夹,否则会报错PermissionError;
① 如果目标文件夹中存在其他文件,会报错;
# 将a文件夹移动到b文件夹,由于前面的操作,此时b文件夹中已经有其他文件
src = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a"
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_b"

shutil.copytree(src,dst)
结果如下:

② 如果指定任意一个目标文件夹,则会自动创建;
# c文件夹原本是不存在的,我们使用了下方的代码,会自动创建该文件夹
src = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a"
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_c"

shutil.copytree(src,dst)
结果如下:

4. 移动文件或文件夹

  • 函数:shutil.move(src,dst)
  • 含义:移动文件/文件夹;-- 参数:src表示源文件/文件夹,dst表示目标文件夹;
  • 注意:文件/文件夹一旦被移动了,原来位置的文件/文件夹就没了。目标文件夹不存在时,会报错;
# 将当前工作目录下的“a.xlsx”文件,移动到a文件夹下
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a"
shutil.move("a.xlsx",dst)
----------------------------------------------------------------
# 将a文件夹下的“a.xlsx”文件,移动到b文件夹中,并重新命名为“aa.xlsx”
src = r"C:/Users/黄伟/Desktop/publish/os模块/test_shutil_a\a.xlsx"
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_b\aa.xlsx"
shutil.move(src,dst)
结果如下:

注意:移动文件夹操作类似,我这里就不赘述了,自行下去学习。

5. 删除文件夹(慎用)

  • 函数:shutil.rmtree(src)
  • 含义:删除文件夹;
  • 参数:src表示源文件夹;
  • 注意:区别这里和os模块中remove()、rmdir()的用法,remove()方法只能删除某个文件,mdir()只能删除某个空文件夹。但是shutil模块中的rmtree()可以递归彻底删除非空文件夹;
# 将c文件夹彻底删除
src = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_c"
shutil.rmtree(src)
结果如下:

6. 创建和解压压缩包

  • zipobj.write():创建一个压缩包;
  • zipobj.namelist():读取压缩包中的文件信息;
  • zipobj.extract():将压缩包中的单个文件,解压出来;
  • zipobj.extractall():将压缩包中所有文件,解压出来;
  • shutil 模块对压缩包的处理是调用 ZipFile 和 TarFile这两个模块来进行的,因此需要导入这两个模块;
  • 注意:这里所说的压缩包,指的是“.zip”格式的压缩包;
① 创建一个压缩包
import zipfile
import os
file_list = os.listdir(os.getcwd())
# 将上述所有文件,进行打包,使用“w”
with zipfile.ZipFile(r"我创建的压缩包.zip""w"as zipobj:
    for file in file_list:
        zipobj.write(file)
结果如下:

② 读取压缩包中的文件信息
import zipfile

with zipfile.ZipFile("我创建的压缩包.zip""r"as zipobj:
    print(zipobj.namelist())
结果如下:

③ 将压缩包中的单个文件,解压出来
  • 注意:目标文件夹不存在,会自动创建;
import zipfile
# 将压缩包中的“test.ipynb”文件,单独解压到a文件夹下
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a"
with zipfile.ZipFile("我创建的压缩包.zip""r"as zipobj:
    zipobj.extract("test.ipynb",dst)
结果如下:

④ 将压缩包中所有文件,解压出来;
  • 注意:目标文件夹不存在,会自动创建;
import zipfile
# 将压缩包中的所有文件,解压到d文件夹下
dst = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_d"
with zipfile.ZipFile("我创建的压缩包.zip""r"as zipobj:
    zipobj.extractall(dst)
结果如下:

五、glob库

1. 支持4个常用的通配符

使用glob模块能够快速查找我们想要的目录和文件,就是由于它支持***?[ ]这三个通配符,那么它们到底是 什么意思呢?
  • *:匹配0个或多个字符;
  • **:匹配所有文件、目录、子目录和子目录里的文件(3.5版本新增);
  • ?:代匹配一个字符;
  • []:匹配指定范围内的字符,如[0-9]匹配数字,[a-z]匹配小写字母;
  • 注意:这3个通配符的用法,将在讲函数的时候,一起带大家操作一遍;

2. glob库中主要的3个函数

其实glob库很简单,只有3个主要函数供我们使用,它们分别是glob()iglob()escape()函数,因此学习起来特别容易。
  • glob.glob():返回符合匹配条件的所有文件的路径;
  • glob.iglob():返回一个迭代器对象,需要循环遍历获取每个元素,得到的也是符合匹配条件的所有文件的路径;
  • glob.escape():escape可以忽略所有的特殊字符,就是星号、问号、中括号,用处不大;
  • recursive=False:代表递归调用,与特殊通配符“**”一同使用,默认为False,False表示不递归调用,True表示递归调用;
① glob()函数
path1 = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a\[0-9].png"
glob.glob(path1)

path2 = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a\[0-9a-z].*"
glob.glob(path2)
结果如下:

② iglob()函数
path1 = r"C:\Users\黄伟\Desktop\publish\os模块\test_shutil_a\[0-9].png"
a = glob.iglob(path1)
for i in a:
    print(i)
结果如下:

③ escape()函数
通过下方两行代码的对比,可以看出escape()函数只是让*只表示它本来的意思,而不再具有通配符的作用。
glob.glob('t*')
glob.escape('t*')
结果如下:

通过上面的叙述可以知道,glob库其实并没有很多东西,就记住3个通配符3个函数即可。对于我们来说,glob库就是方便我们查找文件而诞生的,因此我们好好掌握glob()这一个函数,其实就够了,其它的知道、会用就行。

六、pathlib库

在使用之前,需要提前导入pathlib库。
from pathlib import Path

1. 最重要的Path对象

Path对象是这个库的核心,里面有着超级多好用的文件、文件夹处理方法,供我们调用。
① 当前路径下的Path对象
p = Path.cwd()
p
结果如下:

② 任意指定路径下的Path对象
p = Path('C:/Users/Administrator/Desktop/python三剑客/pathlib库/抽奖.txt')
p
结果如下:

从上图可以看出,Path对象既可以是一个文件对象,也可以是一个文件夹对象。根据不同的对象,调用对应的方法,就可以很便捷的处理文件或文件夹。

2. 获取文件的具体信息

我们既然针对某个文件操作,所以首先应该获取到文件的Path对象。
p = Path("抽奖.txt")
p.stat()
结果如下:

3. 路径拼接

Path对象,进行路径拼接,直接使用一个/斜杠即可。
p = Path('C:/Users/Administrator/Desktop/python三剑客')
p1 = p/'pathlib库'
p1
结果如下:

4. 获取上级目录

p = Path.cwd()
p.parent
p.parent.parent
结果如下:

5. 获取文件的具体信息

我们既然针对某个文件操作,所以首先应该获取到文件的Path对象。
p = Path("抽奖.txt")
p.stat()
结果如下:

6. 获取指定路径下所有文件/文件夹的路径信息

以当前工作目录为例:在当前工作目录下,有下方这些文件。

如何获取每个文件对应的路径信息呢?
p = Path.cwd()
for i in p.iterdir():
    print(i)
结果如下:

「注意:」 iterdir()方法返回的是直接子文件或子文件夹【不考虑嵌套文件夹中的文件】。

7. 获取指定路径下"符合条件"文件的路径信息

仅想要获取直接子文件的路径信息,使用的是glob()方法。
p = Path.cwd()
file_list = p.glob('*.txt')
for file in file_list:
    print(file)
结果如下:

由于需求改变,我不仅想要获取直接子文件的信息,而且还要递归所有文件夹,找到所有符合条件的文件信息?这里有两种办法:
① 方法一
p = Path.cwd()
file_list = p.glob('**/*.txt')
for file  in file_list:
    print(file)
结果如下:

② 方法二
p = Path.cwd()
file_list = p.rglob('*.txt')
for file in file_list:
    print(file)
结果如下:

综上所述:
  • Ⅰ 不考虑嵌套文件夹中的文件,使用glob()方法;
  • Ⅱ 考虑嵌套文件夹中的文件,使用rglob()方法;

8. 限制递归次数,访问嵌套文件夹

「一个粉丝留言问我:」 如果你有一个嵌套文件夹,嵌套次数很深。但是我们并不需要一直访问到最后一层,应该怎么办呢?
① 不限制递归次数
p = Path.cwd()
file_list = p.rglob('*.txt')

for file in file_list:
    print(file)
结果如下:

② 限制递归次数
p = Path.cwd()
file_list = p.rglob('*.txt')

for i,file in enumerate(file_list):
    if i <= 2:
        print(file)
结果如下:

9. 判断当前路径是否存在某个文件或者文件夹

这个需求很有用,比如我们做文件分类的时候,我们需要创建新的文件夹,用于文件分类。此时,我们需要判断,创建的文件夹是否是不存在的,只有不存在我们才去创建这个文件夹。
p = Path.cwd()

for i in p.iterdir():
    print(i)
结果如下:

如果有这么些文件,如何判断文件或文件夹,是否存在呢?

10. 创建文件夹

上面我们如果已经判断了不存在666.txt这个文件,而不存在'b'这个文件夹,现在我们就来创建它。
p = Path.cwd()
p1 = p/'b'

if not Path( 'C:/Users/Administrator/Desktop/python三剑客/pathlib库/b').exists():
    p1.mkdir()
结果如下:

上述我们已经为大家创建了单个文件夹,现在我们来创建一个递归文件夹,这里一定要使用parents=True参数。
p = Path.cwd()
p1 = p/'嵌套第一层'/'嵌套第二层'
p1.mkdir(parents=True)

11. 判断某个路径是文件,还是文件夹

p = Path('C:/Users/Administrator/Desktop/python三剑客/pathlib库/抽奖.txt')
p.is_dir()
p.is_file()
结果如下:

12. 文件/文件夹重命名

p = Path('3.gif')
p.rename("重命名_3.gif")

13. 获取文件的文件名和后缀

这个功能真的很赞,超级好用。
p = Path('C:/Users/Administrator/Desktop/python三剑客/pathlib库/抽奖.txt')
p.name
p.suffix
结果如下:

我们要注意一点,os库shutil库glob库是互补的,我们要善于发挥各自的优势,充分利用它们的优势,帮助我们快速的操作文件和文件夹。
推荐阅读    点击标题可跳转
1. 如何用Python画一只哆啦A梦?
2. 如何用Python分析股票收益率?
3. pprint漂亮的打印,强烈推荐大家学习这个库!
4. 数据分析方法论,大总结!
5. 有了这款Python神器,新手也会调试代码!
6. Pandas与openpyxl库的 "完美" 融合!
7. Python提取PDF简历中的信息,写入Excel
8. Linux系列:完美收官,一共22个课时!
9. Python操作MySQL数据库!
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/124221
 
428 次点击