三、高级应用

该部分包括文件及文件夹操作、PyQt5绘图技术、多线程编程、PyQt5程序的打包发布。学完这一部分,能够开发文件流程序、图形图像程序、多线程应用程序等,能够对PyQt5程序进行打包。

(一)文件及文件夹操作

在变量、序列和对象中存储的数据是暂时的,程序结束后就会丢失,为了能长时间保存程序中的数据,需要将其保存到磁盘文件中。Python中内置了对文件和文件夹进行操作的模块,PyQt5同样提供了对文件和文件夹进行操作的类。
      主要用到的模块有os模块、os.path模块和shutil模块;然后使用PyQt5中的QFile类和QDir类对文件和文件夹操作。在实际开发时,推荐使用Python内置的函数和模块对文件及文件夹进行操作。

1. Python内置的文件操作

Python中内置了文件(File)对象。在使用文件对象时,首先需通过内置的open()方法创建一个文件对象,然后通过该对象提供的方法进行一些基本文件操作。例如,可用文件对象的write()方法向文件中写入内容,以及使用close()方法关闭文件等。

1. 创建和打开文件

在Python中,想要操作文件需要先创建或打开指定的文件并创建文件对象,这里可通过内置的open()方法实现。

open()方法的基本语法

file = open(filename[, mode[, buffering]])

open()方法的参数说明

参数 说明
file 要创建的文件对象。
filename 要创建或打开文件的文件名称,需要用单引号或双引号括起来。如果要打开的文件和当前文件在同一个目录下,那么直接写文件名即可,否则需要指定完整路径。例如,要打开当前路径下的名称为status.txt的文件,可以使用“status.txt”。
mode 可选参数,用于指定文件的打开模式,其参数值如下表。默认的打开模式为只读(即r)。
buffering 可选参数,用于指定读写文件的缓冲模式,值为0表示不缓存; 值为1表示缓存;如果大于1,表示缓冲区的大小。默认为缓存模式。

mode参数的参数值说明

说明 注意
r 以只读模式打开文件。文件的指针将放在文件的开头。 文件必须存在。
rb 以二进制格式打开文件,并且采用只读模式。文件的指针将放在文件的开头。一般用于非文本文件,如图片、声音等。
r+ 打开文件后,可以读取文件内容,也可以写入新的内容覆盖原有内容(从文件开头进行覆盖)。
rb+ 以二进制格式打开文件,并且采用读写模式。文件的指针将会放在文件的开头。一般用于非文本文件,如图片、声音等。
w 以只写模式打开文件。 文件存在,则将其覆盖,否则创建新文件。
wb 以二进制格式打开文件,并且采用只写模式。一般用于非文本文件,如图片、声音等。
w+ 打开文件后,先清空原有内容,使其变为一个空的文件,对这个空文件有读写权限。
wb+ 以二进制格式打开文件。并且采用读写模式。一般用于非文本文件,如图片、声音等。
a 以追加模式打开一个文件。如果该文件已存在,文件指针将放在文件的末尾(即新内容会被写入已有内容之后),否则,创建新文件用于写入。 \
ab 以二进制格式打开文件,并且采用追加模式。如果该文件已经存在,文件指针将放在文件的末尾(即新内容会被写入已有内容之后),否则,创建新文件用于写入。 \
a+ 以读写模式打开文件。如果该文件已经存在,文件指针将放在文件的末尾(即新内容会被写入已有内容之后),否则,创建新文件用于读写。 \
ab+ 以二进制格式打开文件,并且采用追加模式。如果该文件已经存在,文件指针将放在文件的末尾(即新内容会被写入已有内容之后),否则,创建新文件用于读写。 \

默认情况下,使用open()方法打开一个不存在的文件,会抛出下列异常:

      解决该错误的方法有两种:

  1. 在当前目录下(即与执行的文件相同的目录)创建一个名称为x.txt的文件。
  2. 在调用open()方法时,指定mode的参数值为w、w+、a、a+。这样,当要打开的文件不存在时,就可以创建新的文件了。

示例:打开文件,若文件不存在就创建

打开一个名为“message.txt”的文件,如果不存在,则创建。

file = open("message.txt", "w")

执行上面的代码,将在.py文件的同级目录下创建一个名称为message.txt的文件,该文件没有任何内容。

      使用open()方法打开文件时,默认采用GBK编码,当被打开的文件不是GBK编码时,可能会抛出异常。解决该问题的方法有两种,一种是直接修改文件的编码,另一种是在打开文件时,直接指定使用的编码方式。推荐采用后一种方法。在调用open()方法时,通过添加encoding='utf-8’参数即可实现将编码指定为UTF-8。如果想指定其他编码,将单引号中的内容替换为想要指定的编码即可。例如,打开采用UTF-8编码保存的notice.txt文件,可以使用下面代码:

file = open("notice.txt", "r", encoding="utf-8")

2. 关闭文件

打开文件后,需要及时关闭,以免对文件造成不必要的破坏。关闭文件可以使用文件对象的close()方法实现。

close()方法的语法格式

file.close()     # 关闭文件对象
# file为打开的文件对象

使用close()方法时,会先刷新缓冲区中还没有写入的信息,然后再关闭文件,这样可以将没有写入文件的内容写入文件中。在关闭文件后,便不能再进行写入操作了。

3. 打开文件时使用with语句

打开文件后,要及时将其关闭。如果忘记关闭可能会带来意想不到的问题。另外。如果在打开文件时抛出了异常,那么将导致文件不能被及时关闭。为了更好地避免此类问题发生,可以使用Python中提供的with语句,从而实现在处理文件时,无论是否抛出异常,都能保证with语句执行完毕后关闭已经打开的文件。

with语句的基本语法格式

with expression as target:wiht-body

with语句的参数说明

参数 说明
expression 用于指定一个表达式,这里可以是打开文件的open()方法。
target 用于指定一个变量,并且将expression的结果保存到该变量中。
with-body 用于指定with语句体,其中可以是执行with语句后相关的一些操作语句。如果不想执行任何语句,可以直接用pass语句代替。

示例:使用with语句打开文件

在打开文件时使用with语句打开“message.txt”文件:

with open("message.txt", "w") as f:      # 使用with语句打开文件pass

4. 写入文件内容

Python的文件对象提供了write()方法,可以向文件中写入内容。

write()方法的语法格式

file.write(string)
# file为打开的文件对象
# string为要写入的字符串

注意,调用write()方法向文件中写入内容的前提是,打开文件时,指定的打开模式为w(可写)或者a(追加),否则,将抛出下列异常,表示没有写入权限:

示例:向文件中写入文本内容

使用open()方法以写方式打开一个文件(如果文件不存在,则自动创建),然后调用write()方法向该文件中写入一条信息,最后调用close()方法关闭文件。

file = open("message.txt", "w", encoding="utf-8")    # 创建或打卡文件
file.write("故不积跬步,无以至千里;不积小流,无以成江海。\n")    # 写入一条信息
file.close()      # 关闭文件对象

运行程序,在.py文件所在的目录下创建一个名称为message.txt的文件,并且在该文件中写入了文字“故不积跬步,无以至千里;不积小流,无以成江海。“

      注意,写入文件后,一定要调用close()方法关闭文件,否则写入的内容不会保存到文件中。这是因为在写入文件内容时,操作系统不会立刻把数据写入磁盘,而是先缓存起来只有调用close()方法时,操作系统才会保证没有写入的数据全部写入磁盘。

技巧

(1)向文件中写入内容时,如果打开文件采用w(写入)模式,则先清空原文件的内容,再写入新的内容;而如果打开文件采用a(追加)模式,则不覆盖原有文件的内容,知识在文件的结尾处增加新内容。

下面对上面示例的代码进行修改,实现在原内容的基础上再添加一条名言。代码如下:

file = open("message.txt", "a", encoding="utf-8")    # 以追加方式打开文件
file.write("骐骥一跃,不能十步;驽马十驾,功在不舍;锲而舍之,朽木不折;锲而不舍,金石可镂。\n")
file.close()    # 关闭文件对象

执行上面代码,打开message.txt文件,将显示如下效果:

      (2)除了write()方法,Python的文件对象还提供了writelines()方法,可以实现把字符串列表写入文件,但是不添加换行符。

5. 读取文件

在Python中打开文件后,除了可以像其中写入或追加内容,还可以读取文件中的内容。读取文件内容主要分3种情况。

1. 读取指定字符

文件对象提供了read()方法读取指定个数的字符。

read()方法的基本语法
file.read([size])
# file:打开的文件对象。
# size:可选参数,用于指定要读取的字符个数,如果省略,则一次性读取所有内容。

2. 读取一行

在使用read()方法读取文件时,如果文件很大,一次读取全部内容到内存,容易造成内存不足,所以通常会采用逐行读取。文件对象提供了readline()方法用于每次读取一行数据。

readline()方法的基本语法
file.readline()
# file:打开的文件对象。

3. 读取所有行

读取全部行的作用同调用read()方法时不指定size参数类似,只不过读取全部行时,返回的是一个字符串列表,每个元素为文件的一行内容。读取全部行,使用的是文件对象的readlines()方法。

readlines()方法的基本语法
file.readlines()
# file:打开的文件对象。

注意,在读取文件内容时,需要指定文件的打开模式为r(只读)或者r+(读写)。

示例:以3种不同的方式读取文件内容

版本1:没有seek()方法

分别使用read()、readline()、readlines()方法读取文件中的内容。
代码如下:

with open("message.txt", "r", encoding="utf-8") as file:print("==========读取前5个字符==========")print(file.read(5))     # 读取前5个字符print("==========读取第一行数据==========")print(file.readline())    # 读取一行数据print("==========读取所有数据==========")print(file.readlines())      # 读取全部数据

运行效果如下图:

版本2:使用seek()方法
with open("message.txt", "r", encoding="utf-8") as file:print("==========读取前5个字符==========")print(file.read(5))     # 读取前5个字符print("==========读取第一行数据==========")file.seek(0, 0)print(file.readline())    # 读取一行数据print("==========读取所有数据==========")file.seek(0, 0)print(file.readlines())      # 读取全部数据

运行效果如下:

      使用read()方法读取文件时,是从文件的开头读取的。如果想读取部分内容,可以先使用文件对象的seek()方法将文件的指针移动到新的位置,然后再使用read()方法读取。

seek()方法的基本语法
file.seek(offset[, whence])
# offset:用于指定移动的字符个数(offset的值是按一个汉字占两个字符、英文和数字占1个字符计算的),其具体位置与whence有关。
# whence:whence值为0表示从文件头开始计算,1表示从当前位置开始计算,2表示从文件尾开始计算,默认为0。
示例:从文件的第9个字符开始读取5个字符
...file.seek(9)   # 移动文件指针到新的位置string = file.read(5)   # 读取5个字符

6. 复制文件

在Python中复制文件需要使用shutil模块的**copyfile()**方法。

shutil模块的copyfile()方法的基本语法

shutil.copyfile(src, dst)
# src:要复制的源文件。
# dst:复制到的目标文件。

示例:复制文件夹中的图片到项目文件夹中

将D盘“图片”文件夹中的一张图片复制到项目的image文件夹中:

import shutilshutil.copyfile("D:/图片/帕德玛刚玉.png", "./image/宝石之国人物1.png")

运行效果如下:(image文件夹下多了一张图片)

7. 移动文件

在Python中移动文件需要使用shutil模块的move()方法。

shutil模块的move()方法的基本语法

shutil.move(src, dst)
# src:要移动的源文件。
# dst:移动到的目标文件。

示例:将项目的image文件夹中一张图片移动到image文件夹外

import shutilshutil.move("./image/宝石之国人物1.png", "./帕德玛刚玉.png")

运行的效果如下:(原本image文件夹中的图片被移出来了)

原本的目录结构:

      复制文件和移动文件的区别是,复制文件时,源文件还存在,而移动文件相当于将源文件剪切到另外一个路径,源文件不会存在。

8. 重命名文件

在Python中重名名文件需要使用os模块的rename()方法。

os模块的rename()方法的基本语法

os.rename(src, dst)
# src:指定要进行重命名的文件。
# dst:指定重命名后的文件。

示例:将项目中的“message.txt”文件重命名为“text.txt”文件

import os# os.rename("./message.txt", "./image/text.txt")    # 重命名也可以巧用做移动文件
# os.rename("./image/text.txt", "./message.txt")os.rename("message.txt", "text.txt")

运行效果:

      另外,也可以使用shutil模块的move()方法对文件进行重命名。

import shutilshutil.move("text.txt", "message.txt")


      在执行文件操作时,为了确保能够正常执行,可以使用os.pash模块的exists()方法判断要操作的文件是否存在。

示例:使用os.path,exists()方法判断文件是否存在

import os    # 导入os模块if os.path.exists("./message.txt"):    # 判断文件是否存在print("文件存在")

运行效果如下:

9. 删除文件

在Python中删除文件需要使用os模块的remove()方法。

os模块的remove()方法的基本语法

os.remove(path)
# path:表示要删除的文件路径,可以是相对路径,也可以是绝对路径。

示例:删除项目中的"帕德玛刚玉.png"文件

import osos.remove("./帕德玛刚玉.png")

运行后的项目结构:(删除图片)

原本项目结构:

10. 获取文件的基本信息

在计算机上创建文件后,该文件本身就会包含一些信息。例如,文件的最后一次访问时间、最后一次修改时间、文件大小等基本信息。童工os模块的stat()方法可以获取文件的这些基本信息。

os模块的stat()方法的基本语法

os.stat(path)
# path:要获取文件基本信息的文件路径,可以是相对路径,也可以是绝对路径。
# stat()方法的返回值是一个对象,该对象包含下表中所示的属性。通过访问这些属性可以获取文件的基本信息。

stat()方法返回的对象的常用属性

属性 说明
st_mode 保护模式。
st_ino 索引号。
st_size 硬链接号(被连接数目)。
st_mtime 最后一次修改时间。
st_dev 设备名。
st_uid 用户ID。
st_gid 组ID。
st_atime 最后一次访问时间。
st_ctime 最后一次状态变化的时间(系统不同返回结果也不同,例如,在Windows操作系统下返回的是文件的创建时间)。

示例:获取文件基本信息并在PyQt的界面上显示

使用PyQt5设计一个窗口,在其中添加一个PushButton控件,用来选择文件并获取文件的信息;添加一个LineEdit控件,用来显示文件的路径;添加一个TextBrowser控件,用来显示文件的信息。在该窗口中使用QFileDialog类显示文件的对话框,在该文件对话框中选择文件后,使用os.stat()获取选择文件的信息,并显示在TextBrowser控件中。

完整代码如下:

from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import *class Demo(QWidget):def __init__(self, parent=None):super(Demo, self).__init__(parent)self.initUi()     # 初始化窗口def initUi(self):self.setWindowTitle("获取文件信息")grid = QGridLayout()    # 创建网格布局# 创建标签label1 = QLabel()label1.setText("选择路径:")grid.addWidget(label1, 0, 0, QtCore.Qt.AlignLeft)# 创建显示选中文件的文本框self.text1 = QLineEdit()grid.addWidget(self.text1, 0, 1, 1, 3, QtCore.Qt.AlignLeft )# 创建选择按钮btn1 = QPushButton()btn1.setText("选择")btn1.clicked.connect(self.getInfo)grid.addWidget(btn1, 0, 4, QtCore.Qt.AlignCenter)# 显示文件信息的文本浏览器self.text2 = QTextBrowser()grid.addWidget(self.text2, 1, 0, 1, 5, QtCore.Qt.AlignLeft)self.setLayout(grid)    # 设置网格布局# 自定义槽函数def getInfo(self):file = QFileDialog()     # 创建文件对话框file.setDirectory("D:\\")     # 设置初始路径为D盘if file.exec_():      # 判断是否选择了文件filename = file.selectedFiles()[0]     # 获取选择的文件self.text1.setText(filename)      # 将选择的文件显示在文本框中import os, time    # 导入模块fileinfo = os.stat(filename)      # 获取文件信息self.text2.setText("文件完整路径:" + os.path.abspath("filename")+ "\n 文件大小:" + str(fileinfo.st_size) + " 字节"+ "\n 最后一次访问时间:" + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(fileinfo.st_atime))+ "\n 最后一次修改时间:" + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(fileinfo.st_mtime))+ "\n 最后一次状态变化时间:" + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(fileinfo.st_ctime)))if __name__ == "__main__":import sysapp = QApplication(sys.argv)    # 创建窗口程序demo = Demo()    # 创建窗口类对象demo.show()   # 显示窗口sys.exit(app.exec_())

运行程序,单击“选择”按钮,选择一个文件后,即可在下面的文本框中显示其信息:

2. Python内置的文件夹操作

文件夹主要用于分层保存文件,通过文件夹可以分门别类地存放文件。在Python中,并没有提供直接操作文件夹的方法或者对象,而是需要使用内置的os、os.path和shutil模块实现。

1. 获取文件夹路径

用于定位一个文件或者文件夹的字符串被称为一个路径,在程序开发时,通常涉及两种路径,一种是相对路径,另一种是绝对路径。

1. 相对路径

在学习相对路径之前,需要先了解什么是当前工作文件。当前工作文件夹是指当前文件所在的文件夹。在Python中,可以通过os模块提供getcwd()方法获取当前工作文件夹。

示例:用os.getcwd()方法获取当前文件夹路径
import osprint(os.getcwd())   # 输出当前文件夹

执行上面代码,将显示以下文件夹,该路径就是当前工作文件夹。

      相对路径是依赖于当前工作文件夹的,如果在当前工作文件夹下,有一个名称为message.txt的文件,那么在打开这个文件时,就可以直接写上文件名,这时采用的就是相对路径,message.txt文件的实际路径就是当前工作文件夹“E:\program\Python\Code”+相对路径“message.txt”,即“E:\program\Python\Code\message.txt”。
      如果在当前工作文件夹下,有一个子文件夹demo,并且在该子文件夹下保存着文件message.txt,那么在打开这个文件时就可以写上“demo/message.txt”。例如:

with open("demo/message.txt") as file:    # 通过相对路径打开文件pass

在Python中,指定文件路径时需要对路径分隔符“\”进行转义,即将路径中的“\”替换为“\”。例如,对于相对路径“demo\message.txt”需要使用“demo\message.txt”代替。另外,也可以将路径分隔符“\”替换为“/”
      在指定路径时,可以在表示路径的字符串前面加上字母r(或R),那么该字符串将原样输出,这时路径中的分隔符就不需要再转义了。例如,上面的代码也可以修改如下:

with open(r"demo\message.txt") as file:    # 通过相对路径打开文件pass

2. 绝对路径

绝对路径是指在使用文件时指定文件的实际路径,它不依赖于当前工作文件夹。在Python中,可以通过os.path模块提供的abspath()方法获取一个文件夹的绝对路径。

os.path.abspath()方法的基本语法
os.path.abspath(path)
# path:为要获取绝对路径的相对路径,可以是文件,也可以是文件夹。
示例:获取“image\date.png”的绝对路径
import osprint(os.path.abspath(r"image\date.png"))   # 获取绝对路径

运行结果如下:

3. 拼接路径

如果想要将两个或者多个路径拼接到一起组成一个新的路径,可以使用os.path模块提供的join()方法实现。

os.path.join()方法的基本语法
os.path.join(path1[, path2[, ...]])
# path1、path2用于代表要拼接的文件路径,在这些路径间使用逗号进行分隔。
# 如果在要拼接的路径中没有绝对路径,那么最后拼接出来的将是一个相对路径。

注意,使用os.path.join()方法拼接路径时,并不会检测路径是否真实存在。

示例:拼接两个路径“E:\program\Python\Code”和“demo\message.txt”
import osprint(os.path.join("E:\program\Python\Code", "demo\message.txt"))   # 拼接路径

运行结果:

      在使用join()方法时,如果要拼接的路径中存在多个绝对路径,那么以从左到右最后一次出现的为准,并且该路径之前的参数都将被忽略
例如:

import osprint(os.path.join("E:\\code", "E:\\python\\mr", "Code", "C:\\", "demo"))   # 拼接路径

运行结果:

      将两个路径拼接为一个路径时,不要直接使用字符串拼接,而是使用os.path.join()方法,这样可以正确处理不同操作系统的路径分隔符。

2. 判断文件夹是否存在

在Python中,有时需要判断给定的文件夹是否存在,这时可以使用os.path模块提供的exists()方法实现。

os.path.exists()方法的基本语法

os.path.exists(path)
# path:为要判断的文件夹,可以采用绝对路径,也可以采用相对路径。
# 返回值:如果给定的路径存在,则返回True,否则返回False。

示例:pandaUN绝对路径“C:\demo”是否存在

import osprint(os.path.exists(r"C:\demo"))     # 判断文件夹是否存在

实际上C盘没有demo目录,返回结果为False:

3. 创建文件夹

在Python中,os模块提供了两个创建文件夹的方法,一个用于创建一级文件夹,另一个用于创建多级文件夹。

1. 创建一级文件夹

创建一级文件夹是指一次只能创建顶层文件夹,而不能创建子文件夹。在Python中,可以使用os模块提供的mkdir()方法实现。通过该方法只能创建指定路径中的最后一级文件夹,如果该文件夹的上一级不存在,则抛出FileNotFoundError异常。

os.mkdir()方法的基本语法
os.mkdir(path, mode=0o777)
# path:指定要创建的文件夹,可以使用绝对路径,也可以使用相对路径
# mode:指定数值模式,默认值为0o777,。该参数在非UNIX系统上无效或被忽略
示例:在项目中创建一个demo文件夹
import osos.mkdir("./demo")   # 创建demo文件夹

创建文件夹后的项目结构:

原本的项目结构:

      如果创建的文件夹已经存在,将抛出FileExistsError异常,要避免该异常,可以先使用os.path.exists()方法判断要创建的文件夹是否存在。

2. 创建多级文件夹

使用mkdir()方法只能创建一级文件夹,如果想创建多级,可以使用os模块提供的makedirs()方法,该方法用于采用递归的方式创建文件夹。

os.makedirs()方法的基本语法
os.makedirs(name, mode=0o777)
# name:指定要创建的文件夹,可以使用绝对路径,也可以使用相对路径。
# mode:指定数值模式,默认为0o777。该参数在非UNIX系统上无效或被忽略。
示例:在项目中创建文件夹“./demo/test1/test2/test3”
import osos.makedirs("./demo/test1/test2/test3")

执行上面代码,无论中间的test1、test2文件夹是否存在,都可以正常执行。因为如果路径中有文件夹不存在,makedirs()会自动创建。

4. 复制文件夹

在Python中复制文件夹需要使用shutil模块的copytree()方法

shutil.copytree()方法的基本语法

shutil.copytree(src, dst)
# src:要复制的源文件夹
# dst:复制到的目标文件夹

示例:将项目中的demo文件夹复制到项目中的D盘根目录

import shutilshutil.copytree("./demo", "D:/demo_copy")


      在复制文件夹时,如果要复制的文件夹下还有子文件夹,将整体复制到目标文件夹中。

5. 移动文件夹

在Python中移动文件夹需要使用shutil模块的move()方法。

shutil.move()方法的基本语法

shutil.move(src, dst)
# src:要移动的源文件夹。
# dst:移动到的目标文件夹。

示例:将项目中demo文件夹移动到test文件夹中

import shutilshutil.move("./demo", "./test/demo")

移动后的目录结构:

原本的目录结构:

      复制文件夹和移动文件夹的区别是,复制文件夹时,源文件还存在,而移动文件夹相当于将源文件夹剪切到另外一个路径,源文件不会存在。

6. 重命名文件夹

在Python中重命名文件夹需要使用os模块的rename()方法。

os.rename()方法的基本语法

os.rename(src, dst)
# src:指定要进行重命名的文件。
# dst:指定重命名后的文件。

示例:将项目文件夹test文件夹重命名为test_demo

import osos.rename("./test", "test_demo")


      另外,也可以使用shutil模块的move()方法对文件夹进行重命名。

import shutilshutil.move("./test_demo", "./test")

7. 删除文件夹

删除文件夹可以使用os模块提供的rmdir()方法实现。通过rmdir()方法删除文件夹时,只有当删除的文件夹为空时才起作用。如果要删除的文件夹不为空,使用该方法会报错OSError。

os.rmdir()方法的基本语法

os.rmdir(path)
# path:为要删除的文件夹,可以使用相对路径或绝对路径。

示例:删除项目中的test文件夹中最内层的test3文件夹

import osos.rmdir("./test/demo/test1/test2/test3")

删除之后的test文件夹结构:

原本的test文件夹结构:

      使用rmdir()方法只能删除空文件夹,如果想删除非空文件夹,则需要使用Python内置的标准模块shutil的rmtree()方法实现。

示例:使用shutil.rmtree()方法删除非空文件夹test

import shutilshutil.rmtree("./test")   # 删除文件夹下的子文件夹及其包含的所有内容

8. 遍历文件夹

遍历在古汉语中的意思是全部走遍,到处周游。在Python中,遍历的意思也类似,就是对指定的文件夹下的全部文件夹(包括子文件夹)及文件走一遍。在Python中,os模块的walk()方法用于实现遍历文件夹的功能。

os.walk()方法的基本语法

os.walk(top[, topdown][, onerror][, followlinks])
# top:用于指定要遍历内容的根文件夹。
# topdown:可选参数,用于指定遍历的顺序,如果值为True,表示自上而下遍历(即先遍历根文件夹);如果值为False,表示自下而上遍历(即先遍历最后一级子文件夹)。默认为True。
# onerror:可选参数,用于指定错误处理方式,默认为忽略,如果不想忽略也可以指定一个错误处理方法。通常情况下采用默认格式。
# followlinks:可选参数,默认情况下,walk()方法不会向下转换成解析到文件夹的符号链接,将该参数值设置为True,表示用于指定在支持的系统上访问由符号链接指向的文件夹。
# 返回值:返回一个包括3个元素(dirpath,dirnames,filenames)的元组生成器对象。其中,dirpath表示当前遍历的路径,是一个字符串;dirnames表示表示当前路径下包含的子文件夹,是一个列表;filenames表示当前路径下包含的文件,也是一个列表。

示例:遍历文件夹“D:\PyQtLearning\demo\”

import os     # 导入os模块tuples = os.walk("D:\\PyQtLearning\\demo")    # 遍历指定文件夹
for tuple1 in tuples:     # 通过for循环遍历输出结果print(tuple1, "\n")     # 输出每一级文件夹的元组

运行效果如下:

      walk()方法只在Unix和Windows中有效。
      通过walk()方法可以遍历指定文件夹下的所有文件及子文件夹,但这种方法遍历的结果可能会很多,有时我们只需要指定文件夹根目录下的文件和文件夹,该怎么办呢?os模块提供了listdir()方法,可以获取指定文件夹根目录下的所有文件及子文件夹名。

os.listdir()方法的基本语法

os.listdir(path)
# path:表示要遍历的文件夹路径。
# 返回值:返回值是一个列表,包含了所有文件名及子文件夹名。

示例:在Qt界面上显示遍历的指定文件夹“D:\PyQtLeraning\demo”

创建一个.py文件,导入PyQt5相应模块,设计一个窗口程序,在该程序中添加一个PushButton按钮,用来选择路径,并遍历选择的路径;添加一个TableWidget表格控件,用来显示选择的路径;添加一个TableWidget表格控件,用来显示选择路径中包含的所有文件及子文件夹。具体实现时,使用QFileDialog.getExistingDirectory()方法弹出一个选择文件夹的对话框,在该对话框中选择文件夹后,判断如果不为空,则使用os模块的listdir()方法遍历所选择的文件夹,并将其中包含的文件及子文件夹显示在TableWidget表格中。
完整代码如下:

from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtWidgets import QFileDialogclass Ui_MainWindow(object):def setupUi(self, MainWindow):MainWindow.setObjectName("MainWindow")MainWindow.resize(500, 300)   # 设置窗口大小MainWindow.setWindowTitle("遍历文件夹")   # 设置窗口标题self.centralwidget = QtWidgets.QWidget(MainWindow)self.centralwidget.setObjectName("centralwidget")# 添加表格self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)self.tableWidget.setGeometry(QtCore.QRect(0, 40, 501, 270))self.tableWidget.setObjectName("tableWidget")self.tableWidget.setColumnCount(2)    # 设置列数# 设置第一列的标题item = QtWidgets.QTableWidgetItem()self.tableWidget.setHorizontalHeaderItem(0, item)item = self.tableWidget.horizontalHeaderItem(0)item.setText("文件名")# 设置第二列的标题item = QtWidgets.QTableWidgetItem()self.tableWidget.setHorizontalHeaderItem(1, item)item = self.tableWidget.horizontalHeaderItem(1)item.setText("详细信息")self.tableWidget.setColumnWidth(0, 100)   # 设置第一列宽度# 设置最后一列自动填充容器self.tableWidget.horizontalHeader().setStretchLastSection(True)# 创建选择路径按钮self.pushButton = QtWidgets.QPushButton(self.centralwidget)self.pushButton.setGeometry(QtCore.QRect(10, 10, 75, 23))# 为按钮设置字体font = QtGui.QFont()font.setPointSize(10)font.setBold(True)font.setWeight(75)self.pushButton.setFont(font)self.pushButton.setObjectName("pushButton")self.pushButton.setText("选择路径")MainWindow.setCentralWidget(self.centralwidget)QtCore.QMetaObject.connectSlotsByName(MainWindow)self.pushButton.clicked.connect(self.getinfo)    # 关联“选择路径”的clicked信号# 选择路径,并获取其中的所有文件信息,将其显示在表格中def getinfo(self):try:import os# dir_path 为选择的文件夹的绝对路径,第二形参为对话框标题# 第三个为对话框打开后默认的路径self.dir_path = QFileDialog.getExistingDirectory(None, "选择路径", os.getcwd())if self.dir_path != "":self.list = os.listdir(self.dir_path)    # 列出文件夹下所有的目录与文件flag = 0    # 标识插入新行的位置for i in range(0, len(self.list)):      # 遍历文件列表# 拼接路径和文件名filepath = os.path.join(self.dir_path, self.list[i])self.tableWidget.insertRow(flag)    # 添加新行self.tableWidget.setItem(flag, 0, QtWidgets.QTableWidgetItem(self.list[i]))    # 设置第一列的值为文件(夹)名self.tableWidget.setItem(flag, 1, QtWidgets.QTableWidgetItem(filepath))   # 设置第二列的值为文件或文件夹的完整路径flag += 1     # 计算下一个新行的插入位置except Exception as e:print(e)if __name__ == "__main__":import sysapp = QtWidgets.QApplication(sys.argv)MainWindow = QtWidgets.QMainWindow()ui = Ui_MainWindow()ui.setupUi(MainWindow)MainWindow.show()sys.exit(app.exec_())

运行程序,单击“选择路径”按钮,选择一个文件夹后,将会在下面的表格中显示选中文件夹下的所有子文件夹及文件。

3. PyQt5中的文件及文件夹操作

在PyQt5中对文件和文件夹进行操作时,主要用到QFile类、QFileInfo类和QDir类
      在PyQt5窗口程序中对文件或者文件夹进行操作时,不强制必须用PyQt5中提供的QFile、QDir等类,使用Python内置的文件对象同样可以。

1. 使用QFile类操作文件

QFile类主要用来对文件进行打开、读写、复制、重命名、删除等操作。

QFile类的常用方法及说明

方法 说明
open()
  • 打开文件,文件的打开方式可以通过QIODevice的枚举值进行设置,取值如下:
  • QIODevice.NotOpen:不打开;
  • QIODevice.ReadOnly:以只读方式打开;
  • QIODevice.WriteOnly:以只写方式打开;
  • QIODevice.ReadWrite:以读写方式打开;
  • QIODevice.Append:以追加方式打开。
isOpen() 判断文件是否打开。
close() 关闭文件。
copy() 复制文件。
exists() 判断文件是否存在。
read() 从文件中读取指定个数的字符。
readAll() 从文件中读取所有数据。
readLine() 从文件中读取一行数据。
remove() 删除文件。
rename() 重命名文件。
seek() 查找文件。
setFileName() 设置文件名。
write() 向文件中写入数据

获取文件信息需要使用QFileInfo类。

QFileInfo类的常用方法及说明

方法 说明
size() 获取文件大小。
created() 获取文件创建时间。
lastModified() 获取文件最后一次修改时间。
lastRead() 获取文件最后一次访问时间。
isDir() 判断是否是文件夹。
isFile() 判断是否为文件。
isHidden() 判断是否隐藏。
isReadable() 判断是否可读。
isWritable() 判断是否可写。
isExecutable() 判断是否可执行。

示例:按文件存储知乎奇葩问题

爬取知乎上的一篇奇葩问题收集文章,将不同问题保存在不同文件中,放在同一文件夹questions中,文本名称由问题的前5个字+"…"组成。
      在Qt Designer设计器中创建一个窗口,在其中添加两个LineEdit控件,分别用来显示选择的文件和输入文件创建路径;添加两个PushButton控件,分别用来选择存储问题的文件和执行创建文件的功能;添加一个TableWidget控件,用来显示创建的文件列表。窗口设计完成后保存为.ui文件,并使用PyUIC工具将其转换为.py文件。
      在.py文件中,定义两个槽函数,分别用来实现选择存储问题的文本文件,以及根据文件内容创建多个文件,并将内容分别写入不同文件中的功能。

1. 爬取文章和保存问题的代码如下:
# -*- encoding=utf-8 -*-
import requests
import re
import osdef get_text(url):headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36","cookie": 'q_c1=932f9a227b7048bd98d1b6e87539a6dc|1658322630000|1658322630000; _zap=e8dae566-79e6-4384-8211-0576cc5bb078; d_c0="AHCfxXcCRxWPTvpdNJCD-fJm1izHlDzFZ5M=|1658322629"; _9755xjdesxxd_=32; YD00517437729195%3AWM_TID=xYBYS0ziPdREVVUERFaBHBbfytp0AaGd; __snaker__id=3bs9XpTn5qAnjuZv; _xsrf=7f05cb83-9289-49ac-9371-ebf0b500b77d; Hm_lvt_98beee57fd2ef70ccdd5ca52b9740c49=1664287408,1664456793,1665028997,1665380150; gdxidpyhxdE=KVTsfJjcP5BJAoRy%2B%5CVakCk%2BUOZvgONNHVfPZmqDShweJJwEV18q70vZZoqDnwyOgEAED%2FQ7t1Um%5CBg0PG%2F4nkw6T1nnOhdnGmaKyLctJvNeG0kcuj5%5CVvPnluo90GtDiPa6GsoWT1YQep5A8Ub9TsUVf2GoqE0HkP5bPWf9ztQQJ6zv%3A1665381071287; YD00517437729195%3AWM_NI=XYUvqE1R%2B2HtpXMIIYzV4HrD0BFNqGYUp2LetwbCkwkWJ%2BtM%2FlF05Ey5KzQoS3G4AnRDNFxT5JE2JWc6mhS0B5jys%2Fc97CeK8LFIIayRrgd593XeE5Au%2FN6lUrHvgyJwNEk%3D; YD00517437729195%3AWM_NIKE=9ca17ae2e6ffcda170e2e6ee82d3488695a1dad23487ef8ea7c14a939f9ab0c149f59b8f83cb50a7ec9996fc2af0fea7c3b92a9c879b97f44ff38ee5d3cb80b48883aacc53ba8afca9f150f49e8aaff44d9b8bc0d3cf6fb8a9aea4ea7da98986ccf747edb48ad1b84fbbeb859bd46591ed89d5c466929c82a7fb60f7968bd3c95da1eaa389d23c82eba69af225a1e7f9a4e841fc948aaacc6bbb8ebe88e73ffbed9886c83f83abe1afb56897ae8897e6738aa982a6ea37e2a3; captcha_ticket_v2=2|1:0|10:1665380439|17:captcha_ticket_v2|704:eyJ2YWxpZGF0ZSI6IkNOMzFfRlhZLnZ4YjdKN1VtYkNRaHQxMThJaWNPZDVtTUNpeUd1VzVteGdLSl9jU1psSnlzUTBJWHM0MC5qVXJKOEN3UlRMNDdaVC1CeF96SVZESU9YYTZTdi5HNVpKRVN0VjRpcDZ3Z1EueXJ3ZnVTcEVvTUt3amZNUXk5Ul9mZWRDeWxPMk5jTlRqX1JrNWRJWFdCeHhBNDdmQ09EcVY2UVhzWGNvNW9rTGtya2RqcUtub1hySExQZlFDMThWQlNxam9weTVlaTdJRzFXSVMxd0NYVXZ6bmhIRm1vUTF6QVlTenNEemtwN0xZUDhXY3hQZXpJLkV2OVIycW9uNDR6MnlmQjlibnVTTUdUOENrRnBQOGlBcFV5VUt0YTYwYzFOUnI3NFFzbUpfd0tfZkVNOUVQcWZZUGVwQngxellFZ0pkNGlFdDRsMExKeXBOVjJpZ28xbmhxdkg1cHJ2LmdSZ19nSnU5RUdRa1NHTlVIdS51Z2FJalo0RjgtNGFQam9GRFhRcmhKZkhNY0YxbjJtMGFpSnMtQVdJdWRFU29YZWd6ZngxZkdIY0lJZ25QcTdSUGNIWTZ3MVlUNXZFLUFMRHgxdlJEOE16dXYxUS5mN25JLUNVR0xpSGtDemw4bU1HQkp1ZmJPbm9jV2NLaVc4VWNURDdaWmNNSVZnaVpjMyJ9|fb85b43fbcf0cc59411891c15c509e596c550716d89d2eace5d652c4f380340d; z_c0=2|1:0|10:1665380459|4:z_c0|92:Mi4xemU5Tk1RQUFBQUFBY0pfRmR3SkhGU1lBQUFCZ0FsVk5hXzR3WkFEVE8zbHFfZm90MEY4Tzhxc3JwNDVodFdnRkJR|ae1d4b68bd4016632b8c0e8cb46869224034429c152ab8991203180bdbd0c896; captcha_session_v2=2|1:0|10:1665380460|18:captcha_session_v2|88:WU40K3dVeWFYODlKbWZYU1YxbHZSRDQ4TXdCOGN3RkZta2U2TWY2cnlyS3o4enVtck0xZ0pxTjRDdnh1ZWg4cQ==|f6cdb6954c7d4b0140d021284144dd901fed3b69e21607ffacbc4adca2cf5ed6; q_c1=e0a29a67871a4ec588eba3387d49550a|1665380459000|1665380459000; NOT_UNREGISTER_WAITING=1; SESSIONID=aDyGRUvToIzfRLDWQvnopVQmn8g2WAi4pvMu8DXmjKC; JOID=VloQB01WKwh8p-BUcVaPlpve4hdlMWhwOfezJSQ7ZHUb964WIU-cSB-j4VJysJLrK1urWAZ9-s6E2RwGit8niac=; osd=VVoQBUtVKwh-oeNUcVSJlZve4BFmMWhyP_SzJSY9Z3Ub9agVIU-eThyj4VB0s5LrKV2oWAZ__M2E2R4Aid8ni6E=; KLBRSID=d6f775bb0765885473b0cba3a5fa9c12|1665380662|1665380148; Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740c49=1665380667; tst=r'}    # 请求头resp = requests.get(url=url, headers=headers)    # 发起请求text = resp.text   # 获得数据resp.close()   # 关闭请求return text    # 返回数据def main():# url = "https://www.zhihu.com/api/v3/moments?limit=10&desktop=true"url = "https://www.zhihu.com/question/20364508"text = get_text(url)questions = re.findall('class="internal">(.*?)</a>', text)# 删除列表元素的方式一:通过中间列表得到# que = []# for item in questions:#     if item not in que and "??" not in item:#         que.append(item)# for item in que:#     print(item)# del questions    # 删除整个列表# 删除列表的方式二:通过从后往前取下标for i in range(len(questions) - 1, -1, -1):if "??" in questions[i]:questions.remove(questions[i])# # 保存文本:将不同的问题保存在不同文件中,放在questions文件夹中# if not os.path.exists("./questions"):#     os.mkdir("./questions")# for item in questions:#     # 将获取出来的内容保存在文本文件中#     with open(f"./questions/{item[:5]}....txt", "w", encoding="utf-8") as f:#         f.write(item)with open("questions.txt", "w", encoding="utf-8") as f:for item in questions:f.write(item + "\n")if __name__ == "__main__":main()

运行结果:

以下为参考:

问题2:解决删除指定列表元素

在上面代码去掉部分违规数据的时候,使用for-in循环无法删除列表中的指定元素。最终通过网上查找,找到了两种方法,第一种方法是通过中间列表过滤元素,第二种方法是通过for-in-range循环倒序遍历列表进行删除(防止下标越界)。       参考文章:[https://blog.csdn.net/weixin_41666747/article/details/125213619](https://blog.csdn.net/weixin_41666747/article/details/125213619)

问题3:简单正则表达式的使用方法

参考文章:[https://blog.csdn.net/Jakey_src/article/details/122592295](https://blog.csdn.net/Jakey_src/article/details/122592295)

2. 编写PyQt代码
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtCore import QFile, QFileInfo, QIODevice,QTextStream
import os
import datetimeclass Ui_MainWindow(object):def setupUi(self, MainWindow):MainWindow.setObjectName("MainWindow")MainWindow.resize(355, 293)MainWindow.setWindowTitle("将现有问题存放到不同的文件中")self.centralwidget = QtWidgets.QWidget(MainWindow)self.centralwidget.setObjectName("centralwidget")#  分组框self.groupBox = QtWidgets.QGroupBox(self.centralwidget)self.groupBox.setGeometry(QtCore.QRect(10, 10, 331, 91))self.groupBox.setStyleSheet("color: reg(0, 0, 255);")self.groupBox.setObjectName("groupBox")# 选择文件标签self.label = QtWidgets.QLabel(self.groupBox)# self.label.setGeometry(QtCore.QRect(20, 20, 61, 16))self.label.setGeometry(QtCore.QRect(12, 20, 61, 16))self.label.setStyleSheet("color: rgb(0, 0, 0);")     # 设置字体为黑色self.label.setObjectName("label")# 显示选择的文件路径self.lineEdit = QtWidgets.QLineEdit(self.groupBox)# self.lineEdit.setGeometry(QtCore.QRect(80, 20, 171, 20))self.lineEdit.setGeometry(QtCore.QRect(75, 20, 175, 20))self.lineEdit.setObjectName("lineEdit")# “选择”按钮self.pushButton = QtWidgets.QPushButton(self.groupBox)self.pushButton.setGeometry(QtCore.QRect(260, 20, 61, 23))self.pushButton.setStyleSheet("color: rgb(0, 0, 0);")self.pushButton.setObjectName("pushButton")# 输入创建路径标签self.label_2 = QtWidgets.QLabel(self.groupBox)# self.label_2.setGeometry(QtCore.QRect(19, 52, 81, 16))self.label_2.setGeometry(QtCore.QRect(12, 52, 89, 16))self.label_2.setStyleSheet("color: rgb(0, 0, 0);")self.label_2.setObjectName("label_2")# 输入创建路径的文本框self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox)# self.lineEdit_2.setGeometry(QtCore.QRect(109, 52, 141, 20))self.lineEdit_2.setGeometry(QtCore.QRect(105, 52, 145, 20))self.lineEdit_2.setObjectName("lineEdit_2")# 创建“按钮”self.pushButton_2 = QtWidgets.QPushButton(self.groupBox)self.pushButton_2.setGeometry(QtCore.QRect(259, 52, 61, 23))self.pushButton_2.setObjectName("pushButton_2")# 显示创建的文件列表及大小self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)self.tableWidget.setGeometry(QtCore.QRect(10, 105, 331, 181))self.tableWidget.setObjectName("tableWidget")self.tableWidget.setColumnCount(2)# 设置第一列的标题item = QtWidgets.QTableWidgetItem()self.tableWidget.setHorizontalHeaderItem(0, item)item = self.tableWidget.horizontalHeaderItem(0)item.setText("文件名")# 设置第二列标题item = QtWidgets.QTableWidgetItem()self.tableWidget.setHorizontalHeaderItem(1, item)item = self.tableWidget.horizontalHeaderItem(1)item.setText("文件大小")self.tableWidget.setColumnWidth(0, 100)    # 设置第一列宽度# 设置最后一列自动填充容器self.tableWidget.horizontalHeader().setStretchLastSection(True)# 设置分组框、标签及按钮的文本self.groupBox.setTitle("基础设置")self.label.setText("选择文件:")self.label_2.setText("输入创建路径:")self.pushButton.setText("选择")self.pushButton_2.setText("创建")MainWindow.setCentralWidget(self.centralwidget)QtCore.QMetaObject.connectSlotsByName(MainWindow)# 为“选择”按钮的clicked信号绑定槽函数self.pushButton.clicked.connect(self.getfile)# 为“创建”按钮的clicked信号绑定槽函数self.pushButton_2.clicked.connect(self.getpath)# 选择文件并显示在文本框中def getfile(self):dir = QFileDialog()      # 创建文件对话框# dir.setDirectory("D:\\")   # 设置初始路径为D盘dir.setDirectory(".\\")   # 设置初始路径为D盘# 设置只显示文本文件dir.setNameFilter("文本文件(*.txt)")if dir.exec_():    # 判断是否选择了文件self.lineEdit.setText(dir.selectedFiles()[0])     # 将选择的文件显示在文本框中# 选择路径,根据日期创建文件,并写入选择的文件中的文本def getpath(self):try:path = self.lineEdit_2.text()    # 记录创建路径if self.lineEdit_2.text() != "":    # 判断路径不为空list = []     # 定义列表,用来按行记录选择的文件中的文本file = QFile(self.lineEdit.text())    # 创建QFile文件对象if file.open(QIODevice.ReadOnly):     # 以只读方式打开文件read = QTextStream(file)     # 创建文本流read.setCodec("utf-8")    # 设置写入编码while not read.atEnd():     # 如果未读取完list.append(read.readLine())    # 按行记录遍历到的文本# 判断要创建的文件的路径是否存在,没有则创建文件夹if not os.path.exists(path):os.makedirs(path)    # 创建文件夹for i in range(len(list)):     # 遍历已经记录的文本数据列表# 获取当前时间,用来作为文件名mytime = str(datetime.datetime.utcnow().strftime("%Y%m%d%H%M%S"))# 在指定路径下创建txt文本文件files = path + mytime + str(i) + ".txt"file = QFile(files)      # 创建QFile文件对象# 以读写和文本模式打开文件file.open(QIODevice.ReadWrite | QIODevice.Text)file.write(bytes(list[i], encoding="utf8"))     # 向文件中写入数据file.close()    # 关闭文件filelist = os.listdir(path)     # 遍历文件夹flag = 0    # 定义标识,用来指定在表格中的哪行插入数据for f in filelist:     # 遍历文件列表file = QFileInfo(f)         # 创建对象,用来获取文件信息if file.fileName().endswith(".txt"):    # 判断是否为.txt文件self.tableWidget.insertRow(flag)     # 添加新行# 设置第一列的值为文件名self.tableWidget.setItem(flag, 0, QtWidgets.QTableWidgetItem(file.fileName()))# 设置第二列的值为文件大小self.tableWidget.setItem(flag, 1, QtWidgets.QTableWidgetItem(str(file.size()) + "B"))flag += 1     # 标识加1except Exception as e:print(e)if __name__ == "__main__":import sysapp = QtWidgets.QApplication(sys.argv)MainWindow = QtWidgets.QMainWindow()ui = Ui_MainWindow()ui.setupUi(MainWindow)MainWindow.show()sys.exit(app.exec_())

运行程序,单击“选择”按钮,选择存储知乎问题的文本文件,在下面的文本框中输入创建文件的路径,单击“创建”按钮,即可根据选择的we文本文件中的行数创建相应个数的文本文件,并且每一行的内容写入对应的文本文件中。将会在下面的表格中显示选中文件夹下的所有子文件夹及文件。


保存格式二:(以前5个字符+“…”为文件名)

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtCore import QFile, QFileInfo, QIODevice,QTextStream
import os
import datetimeclass Ui_MainWindow(object):def setupUi(self, MainWindow):MainWindow.setObjectName("MainWindow")MainWindow.resize(355, 293)MainWindow.setWindowTitle("将现有问题存放到不同的文件中")self.centralwidget = QtWidgets.QWidget(MainWindow)self.centralwidget.setObjectName("centralwidget")#  分组框self.groupBox = QtWidgets.QGroupBox(self.centralwidget)self.groupBox.setGeometry(QtCore.QRect(10, 10, 331, 91))self.groupBox.setStyleSheet("color: reg(0, 0, 255);")self.groupBox.setObjectName("groupBox")# 选择文件标签self.label = QtWidgets.QLabel(self.groupBox)# self.label.setGeometry(QtCore.QRect(20, 20, 61, 16))self.label.setGeometry(QtCore.QRect(12, 20, 61, 16))self.label.setStyleSheet("color: rgb(0, 0, 0);")     # 设置字体为黑色self.label.setObjectName("label")# 显示选择的文件路径self.lineEdit = QtWidgets.QLineEdit(self.groupBox)# self.lineEdit.setGeometry(QtCore.QRect(80, 20, 171, 20))self.lineEdit.setGeometry(QtCore.QRect(75, 20, 175, 20))self.lineEdit.setObjectName("lineEdit")# “选择”按钮self.pushButton = QtWidgets.QPushButton(self.groupBox)self.pushButton.setGeometry(QtCore.QRect(260, 20, 61, 23))self.pushButton.setStyleSheet("color: rgb(0, 0, 0);")self.pushButton.setObjectName("pushButton")# 输入创建路径标签self.label_2 = QtWidgets.QLabel(self.groupBox)# self.label_2.setGeometry(QtCore.QRect(19, 52, 81, 16))self.label_2.setGeometry(QtCore.QRect(12, 52, 89, 16))self.label_2.setStyleSheet("color: rgb(0, 0, 0);")self.label_2.setObjectName("label_2")# 输入创建路径的文本框self.lineEdit_2 = QtWidgets.QLineEdit(self.groupBox)# self.lineEdit_2.setGeometry(QtCore.QRect(109, 52, 141, 20))self.lineEdit_2.setGeometry(QtCore.QRect(105, 52, 145, 20))self.lineEdit_2.setObjectName("lineEdit_2")# 创建“按钮”self.pushButton_2 = QtWidgets.QPushButton(self.groupBox)self.pushButton_2.setGeometry(QtCore.QRect(259, 52, 61, 23))self.pushButton_2.setObjectName("pushButton_2")# 显示创建的文件列表及大小self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)self.tableWidget.setGeometry(QtCore.QRect(10, 105, 331, 181))self.tableWidget.setObjectName("tableWidget")self.tableWidget.setColumnCount(2)# 设置第一列的标题item = QtWidgets.QTableWidgetItem()self.tableWidget.setHorizontalHeaderItem(0, item)item = self.tableWidget.horizontalHeaderItem(0)item.setText("文件名")# 设置第二列标题item = QtWidgets.QTableWidgetItem()self.tableWidget.setHorizontalHeaderItem(1, item)item = self.tableWidget.horizontalHeaderItem(1)item.setText("文件大小")self.tableWidget.setColumnWidth(0, 100)    # 设置第一列宽度# 设置最后一列自动填充容器self.tableWidget.horizontalHeader().setStretchLastSection(True)# 设置分组框、标签及按钮的文本self.groupBox.setTitle("基础设置")self.label.setText("选择文件:")self.label_2.setText("输入创建路径:")self.pushButton.setText("选择")self.pushButton_2.setText("创建")MainWindow.setCentralWidget(self.centralwidget)QtCore.QMetaObject.connectSlotsByName(MainWindow)# 为“选择”按钮的clicked信号绑定槽函数self.pushButton.clicked.connect(self.getfile)# 为“创建”按钮的clicked信号绑定槽函数self.pushButton_2.clicked.connect(self.getpath)# 选择文件并显示在文本框中def getfile(self):dir = QFileDialog()      # 创建文件对话框# dir.setDirectory("D:\\")   # 设置初始路径为D盘dir.setDirectory(".\\")   # 设置初始路径为D盘# 设置只显示文本文件dir.setNameFilter("文本文件(*.txt)")if dir.exec_():    # 判断是否选择了文件self.lineEdit.setText(dir.selectedFiles()[0])     # 将选择的文件显示在文本框中# 选择路径,根据日期创建文件,并写入选择的文件中的文本def getpath(self):try:path = self.lineEdit_2.text()    # 记录创建路径if self.lineEdit_2.text() != "":    # 判断路径不为空list = []     # 定义列表,用来按行记录选择的文件中的文本file = QFile(self.lineEdit.text())    # 创建QFile文件对象if file.open(QIODevice.ReadOnly):     # 以只读方式打开文件read = QTextStream(file)     # 创建文本流read.setCodec("utf-8")    # 设置写入编码while not read.atEnd():     # 如果未读取完list.append(read.readLine())    # 按行记录遍历到的文本# 判断要创建的文件的路径是否存在,没有则创建文件夹if not os.path.exists(path):os.makedirs(path)    # 创建文件夹for i in range(len(list)):     # 遍历已经记录的文本数据列表# 获取当前时间,用来作为文件名# mytime = str(datetime.datetime.utcnow().strftime("%Y%m%d%H%M%S"))mytime = list[i][:5] + "..."# 在指定路径下创建txt文本文件# files = path + mytime + str(i) + ".txt"files = path + str(i + 1) + ". " + mytime + ".txt"file = QFile(files)      # 创建QFile文件对象# 以读写和文本模式打开文件file.open(QIODevice.ReadWrite | QIODevice.Text)file.write(bytes(list[i], encoding="utf8"))     # 向文件中写入数据file.close()    # 关闭文件filelist = os.listdir(path)     # 遍历文件夹flag = 0    # 定义标识,用来指定在表格中的哪行插入数据for f in filelist:     # 遍历文件列表file = QFileInfo(f)         # 创建对象,用来获取文件信息if file.fileName().endswith(".txt"):    # 判断是否为.txt文件self.tableWidget.insertRow(flag)     # 添加新行# 设置第一列的值为文件名self.tableWidget.setItem(flag, 0, QtWidgets.QTableWidgetItem(file.fileName()))# 设置第二列的值为文件大小self.tableWidget.setItem(flag, 1, QtWidgets.QTableWidgetItem(str(file.size()) + "B"))flag += 1     # 标识加1except Exception as e:print(e)if __name__ == "__main__":import sysapp = QtWidgets.QApplication(sys.argv)MainWindow = QtWidgets.QMainWindow()ui = Ui_MainWindow()ui.setupUi(MainWindow)MainWindow.show()sys.exit(app.exec_())

运行效果:

2. 使用QDir类操作文件夹

QDir类提供对文件夹结构及其内容的访问,使用它可以对文件夹进行创建、重命名、删除、遍历等操作。

QDir类的常用方法及说明

方法 说明
mkdir() 创建文件夹。
exists() 判断文件夹是否存在。
rename() 重命名文件夹。
rmdir() 删除文件夹。
entryList() 遍历文件夹,获取文件夹中所有子文件夹和文件的名称列表。
entryInfoList() 遍历文件夹,获取文件中所有子文件夹和文件的QFileInfo对象的列表。
count() 获取文件夹和文件的数量。
setSorting()
  • 设置entryList()和entryInfoList()使用的排序顺序,取值如下:
  • QDir.Name:按名称排序;
  • QDir.Time:按修改时间排序;
  • QDir.Size:按文件大小排序;
  • QDir.Type:按文件类型排序;
  • QDir.Unsorted:不排序;
  • QDir.DirsFirst:先显示文件夹,然后显示文件;
  • QDir.DirsLast:先显示文件,然后显示文件夹;
  • QDir.Reversed:反向排序;
  • QDir.IgnoreCase:不区分大小写排序;
  • QDir.DefaultSort:默认排序。
path() 获取QDir()对象所关联的文件夹路径。
absolutePath() 获取文件夹的绝对路径。
isAbsolute() 判断是否为绝对路径。
isRelative() 判断是否为相对路径。
isReadable() 判断文件夹是否可读,并且是否能够通过名称打开。
isRoot() 判断是否为根目录。
cd() 改变QDir的路径为dirName。
setFilter()
  • 设置过滤器,以决定entryList()entryInfoList()返回哪些文件,取值如下:
  • QDir.Dirs:按照过滤方式列出所有文件夹;
  • QDir.AllDirs:不考虑过滤方式,列出所有文件夹;
  • QDir.Files:只列出所有文件;
  • QDir.Drives:只列出磁盘(UNIX系统无效);
  • QDir.NoSymLinks:不列出符号连接;
  • QDir.NoDotAndDotDot:不列出“.”和“..”;
  • QDir.AllEntries:列出所有文件夹、w文件和磁盘;
  • QDir.Readble:列出所有具有可读属性的文件夹和文件;
  • QDir.Writable:列出所有具有可写属性的文件夹和文件;
  • QDir.Executable:列出所有具有可执行属性的文件夹和文件;
  • QDir.Modified:列出被修改过的文件夹和文件(UNIX系统无效);
  • QDir.Hidden:列出隐藏的文件夹和文件;
  • Qdir.System:列出系统文件夹和文件;
  • QDir.CaseSensitive:文件系统如果区分文件名大小写,则按大小写方式进行过滤。

示例:使用QDir遍历、重命名和删除文件夹

在Qt Designer设计器中创建一个窗口,在其中添加两个LineEdit控件,分别用来输入路径和要重命名的文件夹名;添加3个PushButton控件,分别用来执行文件夹的遍历、重命名和删除操作;添加一个TableWidget控件,用来显示指定路径下的所有子文件夹。窗口设计完成后保存为.ui文件,并使用PyUIC工具将其转换为.py文件。
      在.py文件中,定义4个槽函数:getItem()、getpath()、rename()和delete(),其中,getItem()用来获取表格中选中的重命名或者删除的文件夹;getpath()用来获取指定路径下的子文件夹,并显示在表格中,如果输入额路径不存在,则自动创建;rename()用来对指定文件夹进行重命名;delete()用来删除指定文件夹。
完整代码如下:

from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import QDir
import osclass Ui_MainWindow(object):def setupUi(self, MainWindow):MainWindow.setObjectName("MainWindow")MainWindow.resize(390, 252)MainWindow.setWindowTitle("QDir应用")   # 设置标题self.centralwidget = QtWidgets.QWidget(MainWindow)self.centralwidget.setObjectName("centralwidget")# 输入路径标签self.label = QtWidgets.QLabel(self.centralwidget)self.label.setGeometry(QtCore.QRect(24, 10, 61, 16))self.label.setObjectName("label")self.label.setText("输入路径:")# 输入路径的文本框self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)self.lineEdit.setGeometry(QtCore.QRect(84, 10, 211, 20))self.lineEdit.setObjectName("lineEdit")# 确定按钮,判断输入路径是否存在,如果不存在,则创建# 如果存在,获取其中的所有文件夹self.pushButton = QtWidgets.QPushButton(self.centralwidget)self.pushButton.setGeometry(QtCore.QRect(304, 10, 61, 23))self.pushButton.setObjectName("pushButton")self.pushButton.setText("确定")# 表格,显示指定路径下的所有文件夹self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)self.tableWidget.setGeometry(QtCore.QRect(14, 40, 351, 171))self.tableWidget.setObjectName("tableWidget")self.tableWidget.setColumnCount(1)item = QtWidgets.QTableWidgetItem()self.tableWidget.setHorizontalHeaderItem(0, item)item = self.tableWidget.horizontalHeaderItem(0)item.setText("路径")self.tableWidget.verticalHeader().setVisible(False)   # 隐藏垂直标题栏# 设置自动填充器self.tableWidget.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)# 设置新文件夹名称标签self.lable_2 = QtWidgets.QLabel(self.centralwidget)self.lable_2.setGeometry(QtCore.QRect(4, 220, 125, 21))self.lable_2.setObjectName("label_2")self.lable_2.setText("设置新文件夹名称:")# 输入新文件夹名称self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget)self.lineEdit_2.setGeometry(QtCore.QRect(130, 220, 81, 20))self.lineEdit_2.setObjectName("lineEdit_2")# 重命名按钮self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_2.setGeometry(QtCore.QRect(220, 220, 61, 23))self.pushButton_2.setObjectName("pushButton_2")self.pushButton_2.setText("重命名")# 删除按钮self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)self.pushButton_3.setGeometry(QtCore.QRect(300, 220, 61, 23))self.pushButton_3.setObjectName("pushButton_3")self.pushButton_3.setText("删除")MainWindow.setCentralWidget(self.centralwidget)QtCore.QMetaObject.connectSlotsByName(MainWindow)# 给控件绑定自定义槽函数:self.pushButton.clicked.connect(self.getpath)self.pushButton_2.clicked.connect(self.rename)self.pushButton_3.clicked.connect(self.delete)self.tableWidget.itemClicked.connect(self.getItem)# 定义 自动以槽函数def getItem(self, item):    # 获取选中的表格内容self.select = item.text()# 获取指定路径下的所有文件夹def getpath(self):self.tableWidget.setRowCount(0)    # 清空表格中的所有行path = self.lineEdit.text()     # 记录输入的路径if path != "":     # 判断路径不为空dir = QDir()    # 创建QDir()对象if not dir.exists(path):     # 判断路径是否存在dir.mkdir(path)     # 如果路径不存在,就创建文件夹dir = QDir(path)   # 创建QDir对象flag = 0    # 定义标识,用来指定在表格中的哪行插入数据# 遍历指定路径下的所有子文件夹for d in dir.entryList(QDir.Dirs | QDir.NoDotAndDotDot):self.tableWidget.insertRow(flag)    # 添加新行# 设置第一列的值为文件夹全路径(包括文件夹名)self.tableWidget.setItem(flag, 0, QtWidgets.QTableWidgetItem(os.path.join(path, d)))flag += 1    # 标识加1# 重命名文件夹def rename(self):newname = self.lineEdit_2.text()   # 记录新文件夹名if newname != "":    # 判断新文件夹名是否为空if self.select != "":    # 判断是偶选择了要重命名的文件夹dir = QDir()   # 创建QDir对象# 对选中的文件夹进行重命名dir.rename(self.select, os.path.join(self.lineEdit.text(), newname))QtWidgets.QMessageBox.information(MainWindow, "提示", "重命名文件夹成功!")self.getpath()    # 更新表格# 删除文件夹def delete(self):if self.select != "":    # 判断是否选择了要删除的文件夹dir = QDir()   # 创建QDir对象dir.rmdir(self.select)    # 删除选中的文件夹QtWidgets.QMessageBox.information(MainWindow, "提示", "成功删除文件夹!")self.getpath()   # 更新表格if __name__ == "__main__":import sysapp = QtWidgets.QApplication(sys.argv)global MainWindowMainWindow = QtWidgets.QMainWindow()ui = Ui_MainWindow()ui.setupUi(MainWindow)MainWindow.show()sys.exit(app.exec_())

运行程序,输入一个路径,单击“确定”按钮,自动遍历改路径下的所有子文件夹,并显示在下方的表格中,如果输入的路径不存在,则自动创建;而当用户选择表格中的某个文件夹后,可以通过单击“重命名”和“删除”按钮,对其进行相应操作。
没有文件夹就自动创建:
重命名文件夹:


删除文件夹:

七、PyQt5文件及文件夹操作(高级应用篇)相关推荐

  1. Python文件(一):文件类型、文件的打开,读取写入,关闭、文件备份、文件和文件夹的操作

    一.文件 文件是存储在存储器上的一组数据序列,可以包含任何数据内容. 文件是数据的抽象和集合. 二.文件类型 文本文件:长字符串 二进制是信息按照非字符但有特定格式形成的文件,文件内部数据的组织格式与 ...

  2. python 文件及文件夹操作

    python 文件.目录操作(新增.移动.删除等) python 文件夹与文件操作 mport string, os, sysdir = '/var' print '----------- no su ...

  3. 计算机文件夹操作教案,文件文件和文件夹教案

    一讲课题目文件和文件夹目录的组织结构及基本操作二教学目标 1知识与技能目标 使学生理解和掌握文件.文件夹的概念.熟练掌握文件和文件夹的基本操作. 2过程与方法目标 通过将文件和文件夹的操作与 ...

  4. wxpython文档_wxPython常用的文件与文件夹操作

    有关文件夹与文件的查找,删除等功能 在os模块中实现.使用时需先导入这个模块, 导入的方法是: import os 一.取得当前目录 s =os.getcwd() # s 中保存的是当前目录(即文件夹 ...

  5. .NET基础-11-ArrayList|Hashtable|File文件操作|Dircetioy文件夹操作|Path路径操作

    集合 ArrayList与Hashtable应为存在拆箱与装箱,所以性能不怎么好,尽量不要使用,而使用泛型集合 可以使用下面的方式输出所消耗的时间 //ArrayList arl = new Arra ...

  6. python文件夹操作_Python文件夹与文件的操作 ZZ

    最近在写的程序频繁地与文件操作打交道,这块比较弱,还好在百度上找到一篇不错的文章,这是原文传送门,我对原文稍做了些改动. 有关文件夹与文件的查找,删除等功能 在 os 模块中实现.使用时需先导入这个模 ...

  7. python文件夹操作指令

    一.取得当前目录 s = os.getcwd() 二.更改当前目录 os.chdir( "C:\\123") 三.判断一个路径( 目录或文件)是否存在 b = os.path.ex ...

  8. python 文件和文件夹操作

    http://blog.csdn.net/hk_jh/article/details/8973116 ---------------------------- 有关文件夹与文件的查找,删除等功能 在  ...

  9. 使用java.io.File操作文件及文件夹

    如果有兴趣了解更多相关内容,可以来我的个人网站看看:eyes++的个人空间 一:File类的概述 java有个io包,java用于操作流的对象都在io包中,io流简单来说就是input和output流 ...

最新文章

  1. UI设计师培训入门都需要学习什么技术?
  2. java switch null_[改善Java代码]小心switch带来的空值异常
  3. Mysql重置初始密码的方法
  4. Java黑皮书课后题第8章:8.28(严格相同的数组)如果两个二维数组m1和m2相应的元素相等的话,则认为它们是严格地相同的。编写一个方法,如果m1和m2是严格相同的话,返回true
  5. matlab应用大全二手,MATLAB应用大全(附光盘)-JobPlus
  6. win7锁定计算机要输入密码登陆,在win7中,怎么解决开机要输入用户密码
  7. css中的单位换算_金蝶ERP入门教程:动态换算率及辅助计量单位的应用
  8. jq之$(“a[target=‘_blank‘]“)
  9. 【thinkphp】ThinkPHP各个低版本(=3.2)完全配置参考手册
  10. 主流物联网平台的架构设计思考
  11. 【Flink】No tests found matching Method xx from org.junit.internal.requests.ClassRequest
  12. 蓝桥杯 基础练习 数的读法
  13. uint8_t / uint16_t / uint32_t /uint64_t
  14. pandownload事件_pandownload被执法背后是中国盗版的末路
  15. 订阅号与服务号的区别
  16. 基于社交网络的推荐算法
  17. 狗民网:狗与爱的世界
  18. C1-01基础任务和知识拓展
  19. lineWithFocusChart(python - nvd3)
  20. 甲骨文oracle云计算迎来转机

热门文章

  1. 中国互联网协会互联网违法和不良信息举报中心曝光一批传播低俗内容的网站名单
  2. gadget之usb_gadget
  3. 在线教育类APP开发系统搭建
  4. H5语音合成SpeechSynthesis
  5. docker环境下安装rockermq以及rockermq-console
  6. android获取屏幕ppi,快速掌握Android屏幕的知识点
  7. 戴尔服务器装w10系统,手把手告诉你戴尔Dell电脑台式如何重装win10系统!
  8. 逆向爬虫31 某站刷播放
  9. typora修改偏好设置不生效/无法修改偏好设置/偏好设置被重置的解决方法
  10. spring cloud 集成 seata 分布式事务