You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Python程序在Mac上向受密码保护的文件追加内容

解决PermissionError并实现密码保护的密码存储文件

先解决当前的PermissionError

你遇到的PermissionError通常是这几个原因:

  • 当前运行程序的用户对passwords.txt所在目录没有写入权限
  • 文件被其他程序占用(比如文本编辑器打开着)
  • 文件本身被设置为只读属性

快速解决方法:

  • 检查文件所在目录的权限,确保当前用户有读写权限
  • 关闭所有可能打开该文件的程序
  • 或者直接指定一个你有权限的路径,比如用户文档目录(需导入os模块):
    file_path = os.path.join(os.path.expanduser("~"), "Documents", "passwords.txt")
    

实现密码保护的文件存储

普通文本文件没法直接设置密码,必须通过加密存储来实现。下面用cryptography库实现基于密码的加密存储,步骤如下:

1. 安装依赖

pip install cryptography

2. 修改后的完整代码

import stdio
import stdrandom
import os
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.backends import default_backend
import base64

def randChar(a):
    stdrandom.shuffle(a)
    return a[0]

def randLetter(a):
    stdrandom.shuffle(a)
    return a[0]

def u_randLetter(a):
    stdrandom.shuffle(a)
    y = a[0]
    return y.upper()

def rand_num():
    return stdrandom.uniformInt(0, 10)

def get_fernet_key(password: str, salt: bytes = None):
    # 生成或使用已有盐值
    if salt is None:
        salt = os.urandom(16)
    # 从密码派生密钥
    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA256(),
        length=32,
        salt=salt,
        iterations=100000,
        backend=default_backend()
    )
    key = base64.urlsafe_b64encode(kdf.derive(password.encode()))
    return key, salt

def load_encrypted_data(file_path: str, password: str):
    try:
        with open(file_path, "rb") as f:
            salt = f.read(16)
            encrypted_data = f.read()
        key, _ = get_fernet_key(password, salt)
        fernet = Fernet(key)
        return fernet.decrypt(encrypted_data).decode()
    except FileNotFoundError:
        # 文件不存在时返回空字符串
        return ""
    except Exception:
        # 密码错误或文件损坏
        stdio.writeln("密码错误或文件损坏!")
        exit(1)

def save_encrypted_data(file_path: str, data: str, password: str):
    key, salt = get_fernet_key(password)
    fernet = Fernet(key)
    encrypted_data = fernet.encrypt(data.encode())
    with open(file_path, "wb") as f:
        f.write(salt)
        f.write(encrypted_data)

def main():
    special_Char = ["!", "@", "#", "$", "%", "^", "&", "*", "-", "+"]
    alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
                "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]

    password = []
    for i in range(4):
        password.append(randLetter(alphabet))
        password.append(rand_num())
        password.append(u_randLetter(alphabet))
        password.append(randChar(special_Char))

    stdrandom.shuffle(password)

    for j in range(len(password)):
        stdio.write(password[j])

    stdio.writeln()

    stdio.writeln("Username:")
    username = stdio.readString()
    stdio.writeln("Website:")
    website = stdio.readString()

    # 提示输入文件密码
    stdio.writeln("请输入文件密码:")
    file_password = stdio.readString()

    # 设置文件路径(可自行修改)
    file_path = os.path.join(os.path.expanduser("~"), "passwords_encrypted.txt")

    # 加载已有加密数据
    existing_data = load_encrypted_data(file_path, file_password)

    # 准备新内容
    new_entry = f"{username}\n{website}\n    Password: "
    for j in range(len(password)):
        new_entry += str(password[j])
    new_entry += "\n\n\n"

    # 合并并保存加密数据
    save_encrypted_data(file_path, existing_data + new_entry, file_password)
    stdio.writeln("密码已成功保存!")

if __name__ == '__main__':
    main()

代码说明

  • 密钥派生:用PBKDF2HMAC从用户输入的密码生成加密密钥,避免直接使用密码作为密钥,提升安全性
  • 加密存储:每次保存时先读取已有加密内容,解密后追加新条目,再重新加密保存
  • 盐值处理:第一次创建文件时自动生成随机盐值,并存入文件开头,解密时读取该盐值派生密钥
  • 错误处理:密码错误或文件损坏时会提示并退出

注意事项

  • 务必牢记文件密码,丢失后无法恢复加密内容
  • 第一次运行时输入的密码将作为后续访问的唯一密码
  • 建议定期备份加密后的文件

内容的提问来源于stack exchange,提问作者Fab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 16:35:18