玖叶教程网

前端编程开发入门

Python学习笔记 | 办公自动化基础之文件和文件夹操作

利用python实现办公自动化的基础就是管理磁盘文件和文件夹,如文件和文件夹的新建、删除、遍历查找等等,使用到的模块有os、shutil、golb、pathlib等。内容虽然简单,但是有些关键点也很容易出错,在这里做一下记录。


一、os模块

系统os模块提供了访问操作系统底层的接口,通过模块众多的方法可以实现对文件和文件夹的基础管理。os模块的方法如下:(前面有★符号的表示是经常使用的方法)

方法名

作 用

★os.listdir

列出指定目录下的所有子目录和文件(不向下遍历)

★os.scandir

扫描指定目录下的所有子目录和文件(不向下遍历)

★os.walk

生成目录树下的所有文件名(遍历所有目录)

★os.getcwd

获取当前工作目录

★os.chdir

改变目录(切换路径)

os.mkdir/makedirs

创建目录/创建多层目录(如:一次性创建a\b\c\d)

os.rmdir/removedirs

删除目录/删除多层目录

os.remove

删除文件

os.rename

重命名文件

★os.path.abspath

获取当前目录的绝对路径

★os.path.basename

获取指定路径中的基本名称(去掉路径)

★os.path.dirname

获取指定路径中的基本路径(去掉文件名)

★os.path.join

将给定的几个基本路径组合成一个路径

★os.path.split

将路径分割成路径和文件名两部分(dirname,basename)

os.path.splitext

将路径分割成路径+文件名(不含扩展名)和扩展名两部分

os.path.getatime

os.path.getctime

os.path.getmtime

获取文件或目录的最近访问、创建和修改时间,返回值是时间戳

os.path.getsize

获取文件尺寸

★os.path.exists

判断路径是否存在

os.path.isabs

判断是否为绝对路径

★os.path.isdir

判断是否为目录

★os.path.isfile

判断是否为文件

下面针对os模块的几个重要方法进行基本讲解:

1、os.listdir方法

os.listdir方法没有多余参数和属性,把子目录名称和文件名称统一放到一个列表里(目录和文件名称里均不含路径信息),使用时需要自行判断列表元素是目录还是文件。os.listdir方法比较简单直接,但是用起来比较顺手。演示代码如下:

import os

# 列出当前目录下的所有子目录和文件
result = os.listdir('./')
# 查看listdir方法的返回值类型
print('返回值类型:', type(result))
# 查看返回结果
for item in result:
    if os.path.isdir(item):
        print(item, '目录')
    else:
        print(item, '文件')

输出结果:
返回值类型: <class 'list'>
test 目录
test.py 文件
搜索文件和文件夹.py 文件
递归遍历目录.py 文件

2、os.scandir方法

os.scandir是Python官方推荐的方法,返回值是一个迭代器,里面的元素是os.DirEntry对象,该对象有两个属性:path和name,path属性中包含路径信息,name属性中不包含路径路径信息。演示代码如下:

import os

# 扫描当前目录下的所有子目录和文件
result = os.scandir('./')
# 查看scandir的返回值类型,结果是迭代器
print(type(result))
# 使用循环遍历输出scandir的结果,有两个属性:path和name
# path属性中包含路径,name属性中不包含路径,只有目录或文件名
for item in result:
    print(item.path, '\t', item.name)

输出结果:
<class 'nt.ScandirIterator'>
./test 	 test
./test.py 	 test.py
./搜索文件和文件夹.py 	 搜索文件和文件夹.py
./递归遍历目录.py 	 递归遍历目录.py

3、os.walk方法

os.walk方法自动遍历指定目录,包括遍历每层的子目录,返回值是一个生成器。它有四个参数:

  • top:指定的顶层目录
  • topdown:可选,为True时,则自上而下,而为False时,则自下而上
  • onerror:可选,是一个函数,OSError实例
  • followlinks:可选,通过软链接访问目录

演示代码如下:

import os

# 遍历指定目录
result = os.walk('./')
# 查看返回类型是生成器
print('返回值类型:', type(result))
# 遍历输出
for item in result:
    print('当前目录:', item[0])
    print('包含目录:', end='')
    for i in item[1]:
        print(i, end=',')
    print()
    print('包含文件:', end='')
    for j in item[2]:
        print(j, end=',')
    print()

输出结果:
返回值类型: <class 'generator'>
当前目录: ./
包含目录:test,
包含文件:test.py,搜索文件和文件夹.py,递归遍历目录.py,
当前目录: ./test
包含目录:
包含文件:

4、os.path.abspath和os.path.join方法

os.path.abspath方法是获取当前目录的绝对路径,os.path.join方法用来将几个子目录名连接成一个完整路径。为什么要将这两个方法放在一起说呢?因为我在分析和学习pygame包自带的一个游戏代码时,发现了官方写代码的方式,全都是考虑了跨平台运行问题。

首先,官方程序的第一行就是#!/usr/bin/env python,这行代码在windows操作系统里运行时会当成注释忽略,而在linux系统里是指定解释器位置,避免程序拿到linux系统运行时出错,这就是考虑了跨平台问题。

然后,再说这两个方法。如果我们在写代码时把路径写成了windows系统的绝对路径,如:d:\python练习\飞机大战,那么你的程序拿到linux系统下是一定运行不起来的,没处去找这个路径,linux系统干脆就不分CDE盘。这时就可以使用这两个方法来解决路径跨平台问题,演示代码如下:

import os

main_dir = os.path.split(os.path.abspath(__file__))[0]
file = os.path.join(main_dir, "data", 'play.py')
print(file)

输出结果:
D:\python练习\办公自动化\data\play.py

代码分析:首先获取当前文件所在位置的绝对路径,__file__表示当前文件,通过切割路径得到主路径;然后使用os.path.join方法,将主路径、子目录和文件名连接成最后想要的完整路径。这些代码里面没有出现任何操作系统的路径格式,这样os.path.abspath方法得到就是当前系统系统的路径格式,join方法同样按照当前操作系统规则进行连接,所以确保跨平台不会出现路径出错问题。

5、其它常用方法

演示代码如下:

import os

print(os.path.basename(r'd:\python练习\飞机大战\plane_main.py'))
输出结果:
plane_main.py

print(os.path.dirname(r'd:\python练习\飞机大战\plane_main.py'))
输出结果:
d:\python练习\飞机大战

print(os.path.join(os.getcwd(), 'test'))
输出结果:
D:\python练习\办公自动化\test

path1 = os.path.split(r'd:\python练习\飞机大战\plane_main.py')
print(path1[0], '\t', path1[1])
输出结果:
d:\python练习\飞机大战 	 plane_main.py

path2 = os.path.splitext(r'd:\python练习\飞机大战\plane_main.py')
print(path2[0], '\t', path2[1])
输出结果:
d:\python练习\飞机大战\plane_main 	 .py

6、综合实例

下面用一个综合实例来演示os模块的主要方法的使用,这个程序不使用os提供的现成遍历函数walk,而是自己编写递归函数,来遍历获取指定目录下的所有文件,旨在深刻理解os模块各个方法的使用。
难点:递归函数从底层目录返回上级目录时,路径非常容易出错,造成返回结果不正常。
解决办法:在每层目录获取到包含的子目录列表时,直接把子目录转换成绝对路径形式再追加到目录列表里。这样在遍历完底层目录返回后,重新获得的路径是绝对路径,确保不出问题。

代码如下:

import os


# 递归函数
def get_allfile(path):
		# 定义全局变量
    global all_list
    # 创建用于包含子目录的列表,初始值为空
    all_dirs = []
    all_files = []
    # 切换到指定目录,这是向出口靠近的条件
    os.chdir(path)
    # 遍历指定目录本层的所有子目录和文件
    for file in os.listdir(path):
        if os.path.isfile(file):
            # 如果是文件就直接追加到当前文件列表中
            all_files.append(file)
        else:
            # 关键:如果是目录,则把该子目录的绝对路径追加到子目录列表中,防止递归往回返时路径出错
            all_dirs.append(os.path.abspath(file))

    # 将当前层目录名、包含的所有子目录和文件以元组形式追加到公共变量all_list列表中
    all_list.append((path, all_dirs, all_files))

    # 如果子目录列表不是空的,说明里面还有子目录,则调用本身继续遍历子目录,否则返回。
    if len(all_dirs):
        for file in all_dirs:
        		# 调用本身,参数是子目录名
            get_allfile(file)
    else:
        # 如果不包含子目录,则返回,这是递归函数的出口。
        return
    return all_list


# 定义一个所有文件的空列表,在递归函数里向该列表里追加遍历到的文件名
all_list = []
# 调用递归函数遍历指定目录
result = get_allfile(r'd:\python练习\飞机大战')
# 循环遍历返回值列表,每个列表元素都是一个三元组
for top_dir, subdir, file in result:
    print('当前目录:', top_dir)
    print('包含目录:')
    for i in subdir:
        print(i, '\t')
    print()
    print('包含文件:')
    for j in file:
        print(j, '\t')
    print()

输出结果:(未列出全部输出结果)
当前目录: d:\python练习\飞机大战
包含目录:
d:\python练习\飞机大战\build 	
d:\python练习\飞机大战\dist 	
d:\python练习\飞机大战\images 	
d:\python练习\飞机大战\sound 	
d:\python练习\飞机大战\__pycache__ 	

包含文件:
plane_main.exe 	
plane_main.py 	
plane_main.spec 	
plane_sprites.py 	
score 	
test.py 	
飞机大战.py 	
飞机大战V2.py 	
飞机大战V3.py 	
飞机大战V4.py 	

二、glob模块

glob模块非常简单,用来查找符合特定规则的目录和文件,返回值是一个列表,主要用作补充和辅助os模块。该模块最大的特点就是支持通配符,因此在查找时就显得非常灵活。

1、通配符

  • *:匹配0个或多个字符
  • **:匹配所有文件、目录、子目录和子目录里的文件
  • ?:匹配一个字符
  • []:匹配指定范围内的字符,如[0-9]匹配数字,[a-z]匹配小写字母

2、三个方法

  • glob.glob方法返回符合匹配条件的所有文件的路径,参数recursive表示递归调用,与特殊通配符“**”一同使用,返回值是列表。
  • glob.iglob方法:跟glob.glob方法一样,返回值是迭代器。
  • glob.escape方法:忽略所有特殊字符的通配符含义

glob模块演示代码如下:

import glob

# 输出指定目录下的所有py文件
print(glob.glob(r'd:\python练习\飞机大战\*.py'))
输出结果:['d:\\python练习\\飞机大战\\plane_main.py', 'd:\\python练习\\飞机大战\\plane_sprites.py', 'd:\\python练习\\飞机大战\\test.py']

# 输出所有t开头的py文件
print(glob.glob(r'd:\python练习\飞机大战\t*.py'))
输出结果:['d:\\python练习\\飞机大战\\test.py']

# 输出当前文件夹下文件名由一个字母构成的py文件
print(glob.glob('./?.py'))
输出结果:['.\\t.py']

# 输出所有文件名后面是数字1的py文件
print(glob.glob('./*[1].py'))
输出结果:['.\\t1.p

# 输出当前文件夹下的所有目录和文件,不向下遍历
print(glob.glob('./**'))
输出结果:['.\\t.py', '.\\t1.py', '.\\test', '.\\test.py', '.\\搜索文件和文件夹.py', '.\\递归遍历目录.py']

# 输出当前文件夹下的所有目录和文件,并遍历所有子文件夹
print(glob.glob('./**',recursive=True))
输出结果:['.\\', '.\\t.py', '.\\t1.py', '.\\test', '.\\test\\find_file.py', '.\\test.py', '.\\搜索文件和文件夹.py', '.\\递归遍历目录.py']

三、shutil模块

shutil是shell until的缩写,同样是作为os模块的补充,提供了复制、移动、删除、压缩、解压等操作。但是,shutil 模块对压缩包的处理是调用 ZipFile 和 TarFile这两个模块来进行的,跟zipfile模块的压缩解压缩是不同的。

常用方法:

  • shutil.copy:复制文件
  • shutil.copytree:复制文件夹
  • shutil.move:移动文件或文件夹
  • shutil.rmtree:删除文件夹
  • zipobj.write:创建一个压缩包
  • zipobj.namelist:读取压缩包中的文件信息
  • zipobj.extract:解压缩单个文件
  • zipobj.extractall:解压缩所有文件

shutil模块使用简单,不再赘述。


四、pathlib模块

pathlib是从python3开始推出的跟os模块功能重叠的内置模块,能够完全替代os.path。Python官网中这样说:“对于字符串的低级路径操作,也可以使用该os.path模块”,这足以证明pathlib有着os.path不能比拟的优点。

在Python 3.4之后,pathlib成为标准库模块,其使用面向对象的编程方式来表示文件系统路径,丰富了路径处理的方法。

1、pathlib模块的优势

  • pathlib实现统一管理,解决了传统操作导入模块不统一问题;
  • pathlib使得在不同操作系统之间切换非常简单;
  • pathlib是面向对象的,路径处理更灵活方便,解决了传统路径和字符串并不等价的问题;
  • pathlib简化了很多操作,简单易用。

2、pathlib模块的主要属性和方法

pathlib模块有一个重要的类——Path,基本上对文件和文件夹的所有操作都是使用Paht的方法和属性完成的,因此重点介绍Paht类的属性和方法的使用。

属性

作 用

Path.name

返回完整文件名(包含后缀),如果是目录则返回目录名

Path.stem

返回文件名(不包含后缀),如果是目录则返回目录名

Path.suffix

返回文件后缀

Path.parents

返回所有上级目录的列表

Path.parts

返回分割路径后的元组

Path.root

返回路径的根目录

Path.driver

返回驱动器名称

方法

作 用

Path.resolve()

获得绝对路径

Path.cwd()

获得当前工作目录

Path.home()

返回电脑的用户目录

Path.stat()

获得文件属性

Path.chmod()

修改文件权限和时间戳

Path.mkdir()

创建目录

Path.rmdir()

删除目录

Path.unlink()

删除一个文件

Path.rename()

文件或文件夹重命名,如果路径不同,会移动并重新命名

Path.replace()

文件或文件夹替换,如果路径不同,会移动并重新命名,如果存在,则破坏现有目标。

Path.open()

打开文件(支持with)

Path.read_bytes()

以字节格式读取文件

Path.read_text()

以文本格式读取文件

Path.write_bytes()

以字节格式写入文件

Path.write_text()

以文本格式写入文件

Path.iterdir()

查找所有子目录和文件,不递归遍历子目录,没有参数

Path.glob()

查找所有文件,不递归遍历子目录,必须指定参数

Path.rglob()

递归遍历目录下的所有子目录和文件,必须指定参数

Path.joinpath()

拼接路径

Path.exists()

判断文件或目录是否存在

Path.is_dir()

判断是否为目录

Path.is_file()

判断是否为文件

Path.is_symlink()

判断是否为符号链接

3、代码演示

from pathlib import Path

# 创建pathlib模块Path类对象
path=Path(r'd:\python练习\飞机大战')
print(path.cwd())  # 输出当前目录
print(path.home())  # 输出电脑的用户目录
输出结果:
D:\python练习\办公自动化
C:\Users\Administrator.User-2022BIVGGU

# 使用Path类拼接路径
path1=Path(path.cwd(),'test')
path2=Path.joinpath(path.cwd(),'test')
print(path1)
print(path2)
输出结果:
D:\python练习\办公自动化\test
D:\python练习\办公自动化\test

path=Path.cwd()
print(path.name)  # 输出当前路径对象的目录名
print(path.stem)  # 输出当前路径对象的目录名
print(Path(r'd:\python练习\飞机大战').name)  # 输出指定目录的当前目录名
输出结果:
办公自动化
办公自动化
飞机大战

# 查找当前目录下的所有py文件,不递归遍历子目录
resulte = path.glob('*.py')  # 必须指定参数
for item in resulte:
    # 分别输出完整文件名,文件名和后缀
    print(item.name, item.stem, item.suffix, sep='  |  ')
输出结果:
t.py  |  t  |  .py
t1.py  |  t1  |  .py
test.py  |  test  |  .py
搜索文件和文件夹.py  |  搜索文件和文件夹  |  .py
递归遍历目录.py  |  递归遍历目录  |  .py

# 遍历当前目录下的所有子目录和文件,不递归遍历子目录
resulte = path.iterdir()  # 不能带参数
for item in resulte:
    # 分别输出完整文件名,文件名和后缀
    print(item.name, item.stem, item.suffix, sep='  |  ')
输出结果:
t.py  |  t  |  .py
t1.py  |  t1  |  .py
test  |  test  |  
test.py  |  test  |  .py
搜索文件和文件夹.py  |  搜索文件和文件夹  |  .py
递归遍历目录.py  |  递归遍历目录  |  .py

# 遍历当前目录下的所有子目录和文件
resulte = path.rglob('*')  # 必须指定参数
for item in resulte:
    # 如果是目录,则输出该目录的绝对路径、子目录名和“子目录”三个文字
    if item.is_dir():
        print(item.resolve(), item.name, '子目录', sep='  |  ')
    # 如果是文件,则输出该文件所在目录的绝对路径、文件名和“文件”两个文字
    elif item.is_file():
        print(item.resolve(), item.name, '文件', sep='  |  ')
输出结果:
D:\python练习\办公自动化\t.py  |  t.py  |  文件
D:\python练习\办公自动化\t1.py  |  t1.py  |  文件
D:\python练习\办公自动化\test  |  test  |  子目录
D:\python练习\办公自动化\test.py  |  test.py  |  文件
D:\python练习\办公自动化\搜索文件和文件夹.py  |  搜索文件和文件夹.py  |  文件
D:\python练习\办公自动化\递归遍历目录.py  |  递归遍历目录.py  |  文件
D:\python练习\办公自动化\test\find_file.py  |  find_file.py  |  文件

综合实例代码:在输入的路径里查找包含输入的关键字的所有目录和文件

from pathlib import Path

# 循环检测输入的路径是否为正确格式并且路径存在
while True:
    top_path = input('请输入搜索起始路径:')
    # 创建pathlib模块的Path类对象,参数中将搜索路径去掉首尾空格
    top_path = Path(top_path.strip())
    # 如果输入路径格式正确并且该路径存在,则中断循环并向下指向
    if top_path.exists() and top_path.is_dir():
        break
    else:
        print('输入的路径有误,请重新输入!')

search = input('请输入搜索关键字:')
result = list(top_path.rglob(f'*{search}*'))
if result:
    result_dir = []
    result_file = []
    for i in result:
        if i.is_dir():
            result_dir.append(i)
        if i.is_file():
            result_file.append(i)
    if result_dir:
        print(f'找到了跟“{search}”相符合的文件夹:')
        for i in result_dir:
            print(i)
    print('-'*30)
    if result_file:
        print(f'找到了跟“{search}”相符合的文件:')
        for i in result_file:
            print(i)
else:
    print(f'抱歉!在路径“{top_path}”里,没有搜索到跟“{search}"符合的文件和文件夹!')

输出结果:
请输入搜索起始路径:d:\python练习\办公自动化
请输入搜索关键字:t
找到了跟“t”相符合的文件夹:
d:\python练习\办公自动化\test
------------------------------
找到了跟“t”相符合的文件:
d:\python练习\办公自动化\t.py
d:\python练习\办公自动化\t1.py
d:\python练习\办公自动化\test.py

五、tempfile模块

tempfile模块的功能是创建临时文件和临时文件夹,程序运行结束后,创建的临时文件和文件夹会自动删除,方便临时转储文件和记录信息。

1、tempfile模块的应用场景

在大型数据处理项目中,有的处理结果是不需要向用户最终展示的,但是它们的应用又是贯穿项目始终的,在这种情况下,我们就需要使用tempfile模块来解决这种问题。

2、tempfile模块的类

tempfile模块供了四个高级类(自动清除关闭的文件)和两个需要手动清理的方法:

  • TemporaryFile类:用于读写临时文件,并且保证临时文件的隐藏性,默认的文件打开模式是w+b。
  • NamedTemporaryFile类:与Temporaryfile类操作类似,但是增加了对文件关闭后是否删除的判断,即delete参数,默认是True。
  • TemporaryDirectory类:安全地创建一个临时目录,返回的对象可用于上下文管理器使用。
  • SpooledTemporaryFile类:在Temporaryfile类基础上增加一个写入闸值Max_size,当数据没有达到max_size时,会暂存在内存中;当数据超过max_size设置的值后,数据会自动写入到临时文件里保存,默认Max_size为0。

3、tempfile模块的方法

  • gettempdir():以文本格式返回系统临时文件夹名
  • gettempdirb():以二进制格式返回系统临时文件夹名
  • gettempprefix():以文本格式返回临时文件名
  • gettempprefixb():以二进制格式返回临时文件名
  • mkstemp() 和 mkdtemp() :底层临时文件和文件夹创建,需要手动清理的方法

4、演示代码

import tempfile


# 输出系统的临时文件夹路径
print('系统的临时文件夹路径是:', tempfile.gettempdir())
# 在当前文件夹里创建临时文件夹
tempdir = tempfile.TemporaryDirectory(dir='./')
print('新建的临时文件夹路径是:', tempdir.name)
# 清除临时文件夹
tempdir.cleanup()

# 使用上下文方式管理临时文件夹,不用调用cleanup方法手动清除
with tempfile.TemporaryDirectory(dir='./') as temp_dir:
    # 使用上下文with模式在新建的临时文件夹中新建临时文件
    with tempfile.TemporaryFile() as temp_file:
        # 写入到临时文件中的信息必须是字节格式
        temp_file.write(b'hello world!')
        # 将指针移动到开始处读取临时文件内容并解码输出
        temp_file.seek(0)
        msg = temp_file.read()
        print(msg.decode())
输出结果:
系统的临时文件夹路径是: C:\Users\ADMINI~1.USE\AppData\Local\Temp
新建的临时文件夹路径是: ./tmph5rj1at5
hello world!

六、zipfile模块

zipfile是压缩和解压缩模块,虽然叫zipfile,但是除了zip之外,rar,war,jar这些压缩(或者打包)文件格式也都可以处理。

1、常用方法

  • ZipFile.getinfo:获取zip文档内指定文件的信息
  • ZipFile.infolist:获取zip文档内所有文件的信息
  • ZipFile.namelist:获取zip文档内所有文件的名称列表。
  • ZipFile.extractall:将zip文档内的指定文件解压到当前目录,参数:member 要解压的文件名称,path解析文件保存的文件夹,pwd 解压密码
  • ZipFile.printdir:将zip文档内的信息打印到控制台上
  • ZipFile.setpassword:设置zip文档的密码
  • ZipFile.read:获取zip文档内指定文件的二进制数据
  • ZipFile.write:将指定文件添加到zip文档中
  • ZipFile.writestr:支持将二进制数据直接写入到压缩文档

2、演示代码

import zipfile
from pathlib import Path

# 创建路径对象
path=Path('./')
# 获取当前文件夹下的所有py文件
files=path.glob('*.py')
# 创建并打开zippy.zip压缩文件
with zipfile.ZipFile('zippy.zip','w') as zipobj:
    # 循环将所有py文件添加到压缩文件中
    for file in files:
        zipobj.write(file)
        print(f'文件{file}被添加到zippy.zip压缩文件中...')
    # 给压缩文件设置密码
    zipobj.setpassword(b"123")
    print('压缩完毕!')
输出结果:
文件t.py被添加到zippy.zip压缩文件中...
文件t1.py被添加到zippy.zip压缩文件中...
文件test.py被添加到zippy.zip压缩文件中...
文件搜索文件和文件夹.py被添加到zippy.zip压缩文件中...
文件递归遍历目录.py被添加到zippy.zip压缩文件中...
压缩完毕!

注:经过测试,添加的密码不起作用,需要深入研究。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言