Python如何实现按文件夹加密解密其中文件

 更新时间:2025年04月25日 11:11:52   作者:学习&实践爱好者  
这篇文章主要为大家详细介绍了一个使用Python实现的按文件夹加密解密其中文件的程序,包含GUI界面和较为完善的功能,感兴趣的小伙伴可以跟随小编一起学习一下

Python实现按文件夹加密解密其中文件工具

一个使用Python实现的按文件夹加密解密其中文件的程序,包含GUI界面和较为完善的功能。我们将使用PyQt6来创建GUI,使用cryptography库进行加密操作。该程序用到一些模块/库:

PyQt6 库是第三方库,需要安装,用于创建图形用户界面(GUI)的库。PyQt6的简介与安装,可参见Pyside6 安装和简单界面开发过程详细介绍

cryptography 是第三方库,需要安装,用于加密和解密的库。

sys、os 和 base64是Python自带的标准库模块,不需要安装。

运行效果

源码如下:

import sys
import os
from PyQt6.QtWidgets import (QApplication, QWidget, QPushButton, QVBoxLayout, 
                            QHBoxLayout, QFileDialog, QLineEdit, QLabel, QMessageBox,
                            QProgressBar, QTextEdit, QSplitter)
from PyQt6.QtCore import Qt, QThread, pyqtSignal
from PyQt6.QtGui import QFont, QColor
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import base64
 
class CryptoWorker(QThread):
    progress = pyqtSignal(int)
    finished = pyqtSignal()
    error = pyqtSignal(str)
    status = pyqtSignal(str)  # 新增状态信号
 
    def __init__(self, folder, password, mode):
        super().__init__()
        self.folder = folder
        self.password = password
        self.mode = mode  # 'encrypt' or 'decrypt'
 
    def run(self):
        try:
            key = self.get_key(self.password)
            fernet = Fernet(key)
 
            total_files = sum([len(files) for r, d, files in os.walk(self.folder)])
            processed_files = 0
            
            self.status.emit(f"开始{'加密' if self.mode == 'encrypt' else '解密'}操作...\n")
 
            for root, dirs, files in os.walk(self.folder):
                for file in files:
                    file_path = os.path.join(root, file)
                    relative_path = os.path.relpath(file_path, self.folder)
                    
                    if self.mode == 'encrypt':
                        if file.endswith('.enc'):
                            self.status.emit(f"跳过已加密文件: {relative_path}")
                        else:
                            self.encrypt_file(fernet, file_path)
                            self.status.emit(f"已加密: {relative_path}")
                    else:  # decrypt
                        if not file.endswith('.enc'):
                            self.status.emit(f"跳过未加密文件: {relative_path}")
                        else:
                            self.decrypt_file(fernet, file_path)
                            self.status.emit(f"已解密: {relative_path}")
                    
                    processed_files += 1
                    self.progress.emit(int(processed_files / total_files * 100))
 
            self.status.emit("\n操作完成!")
            self.finished.emit()
        except Exception as e:
            self.error.emit(str(e))
 
    def get_key(self, password):
        password = password.encode()
        salt = b'salt_'
        kdf = PBKDF2HMAC(
            algorithm=hashes.SHA256(),
            length=32,
            salt=salt,
            iterations=100000,
        )
        key = base64.urlsafe_b64encode(kdf.derive(password))
        return key
 
    def encrypt_file(self, fernet, file_path):
        with open(file_path, 'rb') as f:
            data = f.read()
        encrypted = fernet.encrypt(data)
        encrypted_path = file_path + '.enc'
        with open(encrypted_path, 'wb') as f:
            f.write(encrypted)
        os.remove(file_path)
 
    def decrypt_file(self, fernet, file_path):
        with open(file_path, 'rb') as f:
            data = f.read()
        try:
            decrypted = fernet.decrypt(data)
            decrypted_path = file_path[:-4]  # 移除 '.enc'
            with open(decrypted_path, 'wb') as f:
                f.write(decrypted)
            os.remove(file_path)
        except:
            raise Exception(f'解密 {file_path} 失败,可能密码错误')
 
class Encryptor(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
 
    def initUI(self):
        self.setWindowTitle('文件夹加密器')
        self.setGeometry(300, 200, 700, 600)
 
        main_layout = QVBoxLayout()
 
        # 上半部分:控制面板
        control_panel = QWidget()
        control_layout = QVBoxLayout()
 
        # 文件夹选择
        folder_layout = QHBoxLayout()
        self.folder_input = QLineEdit()
        folder_button = QPushButton('选择文件夹')
        folder_button.clicked.connect(self.select_folder)
        folder_layout.addWidget(self.folder_input)
        folder_layout.addWidget(folder_button)
        control_layout.addLayout(folder_layout)
 
        # 密码输入
        password_layout = QHBoxLayout()
        password_label = QLabel('密码:')
        self.password_input = QLineEdit()
        self.password_input.setEchoMode(QLineEdit.EchoMode.Password)
        password_layout.addWidget(password_label)
        password_layout.addWidget(self.password_input)
        control_layout.addLayout(password_layout)
 
        # 进度条
        self.progress_bar = QProgressBar()
        control_layout.addWidget(self.progress_bar)
 
        # 加密解密按钮
        button_layout = QHBoxLayout()
        encrypt_button = QPushButton('加密')
        decrypt_button = QPushButton('解密')
        encrypt_button.clicked.connect(lambda: self.process_folder('encrypt'))
        decrypt_button.clicked.connect(lambda: self.process_folder('decrypt'))
        button_layout.addWidget(encrypt_button)
        button_layout.addWidget(decrypt_button)
        control_layout.addLayout(button_layout)
 
        control_panel.setLayout(control_layout)
        main_layout.addWidget(control_panel)
 
        # 分割线
        splitter = QSplitter(Qt.Orientation.Vertical)
 
        # 注意事项面板
        notice_panel = QWidget()
        notice_layout = QVBoxLayout()
        notice_label = QLabel("注意事项:")
        notice_label.setFont(QFont("Arial", 12, QFont.Weight.Bold))
        notice_label.setStyleSheet("color: red;")
        notice_text = QTextEdit()
        notice_text.setPlainText(
            "1. 请确保记住密码,否则将无法解密文件。\n"
            "2. 请慎重操作!该程序会直接在原文件夹中操作,谨防误操作。\n"
            "3. 加密后删除原文件,解密后删除加密文件。加密后的文件会有 .enc 扩展名。\n"
            "4. 本程序支持加密/解密文件夹中的所有文件。\n"
            "5. 已加密的文件不会被重复加密,未加密的文件不会被解密。"
        )
        notice_text.setReadOnly(True)
        notice_text.setFont(QFont("Arial", 11))
        notice_text.setStyleSheet("color: #D32F2F;")  # 深红色
        notice_layout.addWidget(notice_label)
        notice_layout.addWidget(notice_text)
        notice_panel.setLayout(notice_layout)
 
        # 日志面板
        log_panel = QWidget()
        log_layout = QVBoxLayout()
        log_label = QLabel("处理日志:")
        #log_label.setFont(QFont("Arial", 10, QFont.Weight.Bold))
        self.log_text = QTextEdit()
        self.log_text.setReadOnly(True)
        #self.log_text.setFont(QFont("Arial", 10))
        log_layout.addWidget(log_label)
        log_layout.addWidget(self.log_text)
        log_panel.setLayout(log_layout)
 
        # 添加面板到分割器
        splitter.addWidget(notice_panel)
        splitter.addWidget(log_panel)
        main_layout.addWidget(splitter)
 
        self.setLayout(main_layout)
 
    def select_folder(self):
        folder = QFileDialog.getExistingDirectory(self, "选择文件夹")
        self.folder_input.setText(folder)
 
    def process_folder(self, mode):
        folder = self.folder_input.text()
        password = self.password_input.text()
        if not folder or not password:
            QMessageBox.warning(self, '警告', '请选择文件夹并输入密码')
            return
 
        # 清空日志
        self.log_text.clear()
        
        self.worker = CryptoWorker(folder, password, mode)
        self.worker.progress.connect(self.update_progress)
        self.worker.finished.connect(self.process_finished)
        self.worker.error.connect(self.process_error)
        self.worker.status.connect(self.update_log)  # 连接状态信号
        self.worker.start()
 
    def update_progress(self, value):
        self.progress_bar.setValue(value)
 
    def update_log(self, message):
        self.log_text.append(message)
 
    def process_finished(self):
        QMessageBox.information(self, '成功', '操作完成')
        self.progress_bar.setValue(0)
 
    def process_error(self, error_msg):
        QMessageBox.critical(self, '错误', f'发生错误:{error_msg}')
        self.progress_bar.setValue(0)
        self.log_text.append(f"\n错误: {error_msg}")
 
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Encryptor()
    ex.show()
    sys.exit(app.exec())

到此这篇关于Python如何实现按文件夹加密解密其中文件的文章就介绍到这了,更多相关Python加密解密文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python opencv鼠标画矩形框之cv2.rectangle()函数

    python opencv鼠标画矩形框之cv2.rectangle()函数

    鼠标操作属于用户接口设计,以前一直使用Qt来做,但是如果只需要简单的鼠标,键盘操作,直接调用opencv库的函数也未尝不可,下面这篇文章主要给大家介绍了关于python opencv鼠标画矩形框cv2.rectangle()函数的相关资料,需要的朋友可以参考下
    2021-10-10
  • PySide(PyQt)使用QPropertyAnimation制作动态界面的示例代码

    PySide(PyQt)使用QPropertyAnimation制作动态界面的示例代码

    文章介绍了如何使用PySide或PyQt的QPropertyAnimation类来创建动态界面效果,感兴趣的朋友一起看看吧
    2025-03-03
  • python执行数据库的查询操作实例讲解

    python执行数据库的查询操作实例讲解

    在本篇文章里小编给大家整理了一篇关于python执行数据库的查询操作实例讲解内容,有需要的朋友们可以参考学习下。
    2021-10-10
  • 详解python itertools功能

    详解python itertools功能

    itertools是python内置的模块,使用简单且功能强大,这里尝试汇总整理下,并提供简单应用示例,这篇文章主要介绍了python itertools功能,需要的朋友可以参考下
    2020-02-02
  • Python 关于模块和加载模块的实现

    Python 关于模块和加载模块的实现

    这篇文章主要介绍了Python 关于模块和加载模块的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Flask缓存静态文件的具体方法

    Flask缓存静态文件的具体方法

    在本篇文章中小编给大家整理的是一篇关于Flask缓存静态文件的具体方法,有需要的朋友们可以参考下。
    2020-08-08
  • python绘图模块matplotlib示例详解

    python绘图模块matplotlib示例详解

    这篇文章主要介绍了python绘图模块matplotlib示例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • python中的selenium入门超详细教程

    python中的selenium入门超详细教程

    这篇文章主要介绍了python中的selenium入门超详细教程,本文是在python环境下使用selenium,使用浏览器是Chrome,系统是win10系统,需要的朋友可以参考下
    2023-11-11
  • Python自动化测试中yaml文件读取操作

    Python自动化测试中yaml文件读取操作

    这篇文章主要介绍了Python自动化测试中yaml文件读取操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • Python使用Windows API创建窗口示例【基于win32gui模块】

    Python使用Windows API创建窗口示例【基于win32gui模块】

    这篇文章主要介绍了Python使用Windows API创建窗口操作,结合实例形式分析了Python基于win32gui模块调用Windows API创建窗口具体操作步骤与相关实现技巧,需要的朋友可以参考下
    2018-05-05

最新评论